@saptools/bruno 0.3.0 → 0.3.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/README.md +7 -5
- package/dist/cli.js +490 -494
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +56 -56
- package/dist/index.js +233 -231
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts","../src/paths.ts","../src/bru-parser.ts","../src/bru-writer.ts","../src/cf-info.ts","../src/cf-meta.ts","../src/folder-scan.ts","../src/context.ts","../src/setup-app.ts","../src/run.ts","../src/use.ts"],"sourcesContent":["import type { RegionKey } from \"@saptools/cf-sync\";\n\nexport interface CfAppRef {\n readonly region: RegionKey;\n readonly org: string;\n readonly space: string;\n readonly app: string;\n}\n\nexport interface BruVarsBlock {\n readonly entries: ReadonlyMap<string, string>;\n}\n\nexport interface BruEnvFile {\n readonly path: string;\n readonly name: string;\n readonly raw: string;\n readonly vars: BruVarsBlock;\n readonly secrets: readonly string[];\n}\n\nexport interface AppFolder {\n readonly path: string;\n readonly name: string;\n readonly environments: readonly BruEnvFile[];\n}\n\nexport interface SpaceFolder {\n readonly path: string;\n readonly name: string;\n readonly apps: readonly AppFolder[];\n}\n\nexport interface OrgFolder {\n readonly path: string;\n readonly name: string;\n readonly spaces: readonly SpaceFolder[];\n}\n\nexport interface RegionFolder {\n readonly path: string;\n readonly key: string;\n readonly orgs: readonly OrgFolder[];\n}\n\nexport interface BrunoCollection {\n readonly root: string;\n readonly regions: readonly RegionFolder[];\n}\n\nexport interface BrunoContext {\n readonly region: string;\n readonly org: string;\n readonly space: string;\n readonly app: string;\n readonly updatedAt: string;\n}\n\nexport interface CfRoute {\n readonly url: string;\n}\n\nexport const CF_META_KEYS = [\"__cf_region\", \"__cf_org\", \"__cf_space\", \"__cf_app\"] as const;\nexport type CfMetaKey = (typeof CF_META_KEYS)[number];\n","import { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport const SAPTOOLS_DIR_NAME = \".saptools\";\nexport const BRUNO_CONTEXT_FILENAME = \"bruno-context.json\";\n\nexport const REGION_FOLDER_PREFIX = \"region__\";\nexport const ORG_FOLDER_PREFIX = \"org__\";\nexport const SPACE_FOLDER_PREFIX = \"space__\";\nexport const ENVIRONMENTS_DIR = \"environments\";\n\nexport function saptoolsDir(): string {\n return join(homedir(), SAPTOOLS_DIR_NAME);\n}\n\nexport function brunoContextPath(): string {\n return join(saptoolsDir(), BRUNO_CONTEXT_FILENAME);\n}\n\nexport function regionFolderName(key: string): string {\n return `${REGION_FOLDER_PREFIX}${key}`;\n}\n\nexport function orgFolderName(name: string): string {\n return `${ORG_FOLDER_PREFIX}${name}`;\n}\n\nexport function spaceFolderName(name: string): string {\n return `${SPACE_FOLDER_PREFIX}${name}`;\n}\n\nexport function parsePrefixedName(\n dirName: string,\n prefix: string,\n): string | undefined {\n if (!dirName.startsWith(prefix)) {\n return undefined;\n }\n return dirName.slice(prefix.length);\n}\n","import type { BruVarsBlock } from \"./types.js\";\n\ninterface BlockRange {\n readonly header: string;\n readonly start: number;\n readonly end: number;\n readonly bodyStart: number;\n readonly bodyEnd: number;\n readonly open: \"{\" | \"[\";\n readonly close: \"}\" | \"]\";\n}\n\nconst HEADER_REGEX = /(^|\\n)[^\\S\\n]*([a-zA-Z][a-zA-Z0-9:_-]*)[^\\S\\n]*([{[])/g;\n\nfunction findMatchingClose(raw: string, open: \"{\" | \"[\", openIdx: number): number {\n const close = open === \"{\" ? \"}\" : \"]\";\n let depth = 1;\n let i = openIdx + 1;\n while (i < raw.length) {\n const ch = raw[i];\n if (ch === open) {\n depth++;\n } else if (ch === close) {\n depth--;\n if (depth === 0) {\n return i;\n }\n }\n i++;\n }\n return -1;\n}\n\nexport function listBlocks(raw: string): readonly BlockRange[] {\n const blocks: BlockRange[] = [];\n HEADER_REGEX.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = HEADER_REGEX.exec(raw)) !== null) {\n const leadingNewline = match[1] ?? \"\";\n const header = match[2];\n const open = match[3];\n if (header === undefined || (open !== \"{\" && open !== \"[\")) {\n continue;\n }\n const headerStart = match.index + leadingNewline.length;\n const openIdx = match.index + match[0].length - 1;\n const closeIdx = findMatchingClose(raw, open, openIdx);\n if (closeIdx === -1) {\n continue;\n }\n blocks.push({\n header,\n start: headerStart,\n end: closeIdx + 1,\n bodyStart: openIdx + 1,\n bodyEnd: closeIdx,\n open,\n close: open === \"{\" ? \"}\" : \"]\",\n });\n }\n return blocks;\n}\n\nexport function parseKeyValueBody(body: string): Map<string, string> {\n const entries = new Map<string, string>();\n for (const lineRaw of body.split(\"\\n\")) {\n const line = lineRaw.trim();\n if (line.length === 0 || line.startsWith(\"//\")) {\n continue;\n }\n const colon = line.indexOf(\":\");\n if (colon === -1) {\n continue;\n }\n const key = line.slice(0, colon).trim();\n const value = line.slice(colon + 1).trim();\n if (key.length > 0) {\n entries.set(key, value);\n }\n }\n return entries;\n}\n\nexport function parseListBody(body: string): string[] {\n const items: string[] = [];\n for (const lineRaw of body.split(\"\\n\")) {\n const line = lineRaw.trim();\n if (line.length === 0 || line.startsWith(\"//\")) {\n continue;\n }\n items.push(line);\n }\n return items;\n}\n\nexport interface ParsedBruEnv {\n readonly vars: BruVarsBlock;\n readonly secrets: readonly string[];\n}\n\nexport function parseBruEnvFile(raw: string): ParsedBruEnv {\n const blocks = listBlocks(raw);\n const varsBlock = blocks.find((b) => b.header === \"vars\" && b.open === \"{\");\n const secretsBlock = blocks.find((b) => b.header === \"vars:secret\" && b.open === \"[\");\n\n const entries = varsBlock\n ? parseKeyValueBody(raw.slice(varsBlock.bodyStart, varsBlock.bodyEnd))\n : new Map<string, string>();\n const secrets = secretsBlock\n ? parseListBody(raw.slice(secretsBlock.bodyStart, secretsBlock.bodyEnd))\n : [];\n\n return { vars: { entries }, secrets };\n}\n","import { listBlocks, parseKeyValueBody } from \"./bru-parser.js\";\n\nexport interface UpsertResult {\n readonly content: string;\n readonly changed: boolean;\n}\n\nfunction formatVarsBlock(entries: ReadonlyMap<string, string>): string {\n const lines: string[] = [];\n for (const [key, value] of entries) {\n lines.push(` ${key}: ${value}`);\n }\n return lines.join(\"\\n\");\n}\n\nexport function upsertVars(\n raw: string,\n updates: ReadonlyMap<string, string>,\n): UpsertResult {\n const blocks = listBlocks(raw);\n const varsBlock = blocks.find((b) => b.header === \"vars\" && b.open === \"{\");\n\n if (!varsBlock) {\n const newBlock = `vars {\\n${formatVarsBlock(updates)}\\n}\\n`;\n const sep = raw.length > 0 && !raw.endsWith(\"\\n\") ? \"\\n\\n\" : raw.length > 0 ? \"\\n\" : \"\";\n return { content: `${raw}${sep}${newBlock}`, changed: updates.size > 0 };\n }\n\n const body = raw.slice(varsBlock.bodyStart, varsBlock.bodyEnd);\n const existing = parseKeyValueBody(body);\n let changed = false;\n for (const [k, v] of updates) {\n if (existing.get(k) !== v) {\n existing.set(k, v);\n changed = true;\n }\n }\n\n if (!changed) {\n return { content: raw, changed: false };\n }\n\n const rebuilt = `\\n${formatVarsBlock(existing)}\\n`;\n const before = raw.slice(0, varsBlock.bodyStart);\n const after = raw.slice(varsBlock.bodyEnd);\n return { content: `${before}${rebuilt}${after}`, changed: true };\n}\n\nexport function ensureSecretEntry(raw: string, secretName: string): UpsertResult {\n const blocks = listBlocks(raw);\n const secretsBlock = blocks.find((b) => b.header === \"vars:secret\" && b.open === \"[\");\n\n if (!secretsBlock) {\n const newBlock = `vars:secret [\\n ${secretName}\\n]\\n`;\n const sep = raw.length > 0 && !raw.endsWith(\"\\n\") ? \"\\n\\n\" : raw.length > 0 ? \"\\n\" : \"\";\n return { content: `${raw}${sep}${newBlock}`, changed: true };\n }\n\n const body = raw.slice(secretsBlock.bodyStart, secretsBlock.bodyEnd);\n const items = body\n .split(\"\\n\")\n .map((l) => l.trim())\n .filter((l) => l.length > 0 && !l.startsWith(\"//\"));\n if (items.includes(secretName)) {\n return { content: raw, changed: false };\n }\n items.push(secretName);\n const rebuilt = `\\n ${items.join(\"\\n \")}\\n`;\n const before = raw.slice(0, secretsBlock.bodyStart);\n const after = raw.slice(secretsBlock.bodyEnd);\n return { content: `${before}${rebuilt}${after}`, changed: true };\n}\n","import type {\n CfStructure,\n OrgNode,\n RegionKey,\n RegionNode,\n RegionsView,\n RegionView,\n SpaceNode,\n StructureView,\n} from \"@saptools/cf-sync\";\nimport {\n getRegionView as getRegionViewApi,\n readRegionsView,\n readRegionView,\n readStructureView,\n REGION_KEYS,\n} from \"@saptools/cf-sync\";\n\nexport interface CfInfoDeps {\n readonly readStructureView: () => Promise<StructureView | undefined>;\n readonly readRegionsView: () => Promise<RegionsView>;\n readonly readRegionView: (key: RegionKey) => Promise<RegionView | undefined>;\n readonly getRegionView: (opts: {\n readonly regionKey: RegionKey;\n readonly email?: string;\n readonly password?: string;\n readonly refreshIfMissing?: boolean;\n }) => Promise<RegionView | undefined>;\n}\n\nexport const defaultCfInfoDeps: CfInfoDeps = {\n readStructureView,\n readRegionsView,\n readRegionView,\n getRegionView: getRegionViewApi,\n};\n\nexport function isValidRegionKey(value: string): value is RegionKey {\n return (REGION_KEYS as readonly string[]).includes(value);\n}\n\nexport interface StructureSnapshot {\n readonly source: \"runtime\" | \"stable\" | \"empty\";\n readonly structure: CfStructure | undefined;\n readonly stale: boolean;\n readonly message: string | undefined;\n}\n\nexport async function getStructureSnapshot(\n deps: CfInfoDeps = defaultCfInfoDeps,\n): Promise<StructureSnapshot> {\n const view = await deps.readStructureView();\n if (!view) {\n return {\n source: \"empty\",\n structure: undefined,\n stale: true,\n message: \"No CF structure cached. Run `cf-sync sync` first.\",\n };\n }\n\n const stale = view.source === \"runtime\" && view.metadata?.status === \"running\";\n return {\n source: view.source,\n structure: view.structure,\n stale,\n message: stale ? \"A CF sync is still running — showing partial data.\" : undefined,\n };\n}\n\nexport interface RegionSuggestion {\n readonly key: RegionKey;\n readonly label: string;\n readonly orgCount: number;\n}\n\nexport async function listRegionsWithContent(\n deps: CfInfoDeps = defaultCfInfoDeps,\n): Promise<readonly RegionSuggestion[]> {\n const snapshot = await getStructureSnapshot(deps);\n if (!snapshot.structure) {\n return [];\n }\n return snapshot.structure.regions\n .filter((r) => r.accessible && r.orgs.length > 0)\n .map((r) => ({ key: r.key, label: r.label, orgCount: r.orgs.length }));\n}\n\nexport async function getRegion(\n key: RegionKey,\n deps: CfInfoDeps = defaultCfInfoDeps,\n): Promise<RegionNode | undefined> {\n const view = await deps.readRegionView(key);\n return view?.region;\n}\n\nexport function findOrg(region: RegionNode, orgName: string): OrgNode | undefined {\n return region.orgs.find((o) => o.name === orgName);\n}\n\nexport function findSpace(org: OrgNode, spaceName: string): SpaceNode | undefined {\n return org.spaces.find((s) => s.name === spaceName);\n}\n\nexport function findApp(space: SpaceNode, appName: string): { readonly name: string } | undefined {\n return space.apps.find((a) => a.name === appName);\n}\n\nexport interface ResolvedRef {\n readonly region: RegionNode;\n readonly org: OrgNode;\n readonly space: SpaceNode;\n readonly app: { readonly name: string };\n}\n\nexport async function resolveRef(\n ref: {\n readonly region: RegionKey;\n readonly org: string;\n readonly space: string;\n readonly app: string;\n },\n deps: CfInfoDeps = defaultCfInfoDeps,\n): Promise<ResolvedRef | undefined> {\n const region = await getRegion(ref.region, deps);\n if (!region) {\n return undefined;\n }\n const org = findOrg(region, ref.org);\n if (!org) {\n return undefined;\n }\n const space = findSpace(org, ref.space);\n if (!space) {\n return undefined;\n }\n const app = findApp(space, ref.app);\n if (!app) {\n return undefined;\n }\n return { region, org, space, app };\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\n\nimport { parseBruEnvFile } from \"./bru-parser.js\";\nimport { upsertVars } from \"./bru-writer.js\";\nimport { CF_META_KEYS } from \"./types.js\";\nimport type { CfAppRef, CfMetaKey } from \"./types.js\";\n\nexport interface CfMeta {\n readonly region: string;\n readonly org: string;\n readonly space: string;\n readonly app: string;\n}\n\nexport function readCfMetaFromVars(vars: ReadonlyMap<string, string>): CfMeta | undefined {\n const region = vars.get(\"__cf_region\");\n const org = vars.get(\"__cf_org\");\n const space = vars.get(\"__cf_space\");\n const app = vars.get(\"__cf_app\");\n if (!region || !org || !space || !app) {\n return undefined;\n }\n return { region, org, space, app };\n}\n\nexport function buildCfMetaUpdates(ref: CfAppRef, baseUrl?: string): Map<string, string> {\n const updates = new Map<string, string>();\n const pairs: readonly [CfMetaKey, string][] = [\n [\"__cf_region\", ref.region],\n [\"__cf_org\", ref.org],\n [\"__cf_space\", ref.space],\n [\"__cf_app\", ref.app],\n ];\n for (const [k, v] of pairs) {\n updates.set(k, v);\n }\n if (baseUrl !== undefined) {\n updates.set(\"baseUrl\", baseUrl);\n }\n return updates;\n}\n\nexport function hasCfMeta(vars: ReadonlyMap<string, string>): boolean {\n return CF_META_KEYS.every((k) => {\n const v = vars.get(k);\n return v !== undefined && v.length > 0;\n });\n}\n\nexport async function readCfMetaFromFile(path: string): Promise<CfMeta | undefined> {\n const raw = await readFile(path, \"utf8\");\n const parsed = parseBruEnvFile(raw);\n return readCfMetaFromVars(parsed.vars.entries);\n}\n\nexport async function writeCfMetaToFile(\n path: string,\n ref: CfAppRef,\n baseUrl?: string,\n): Promise<boolean> {\n const raw = await readFile(path, \"utf8\");\n const updates = buildCfMetaUpdates(ref, baseUrl);\n const { content, changed } = upsertVars(raw, updates);\n if (changed) {\n await writeFile(path, content, \"utf8\");\n }\n return changed;\n}\n","import { readdir, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { parseBruEnvFile } from \"./bru-parser.js\";\nimport {\n ENVIRONMENTS_DIR,\n ORG_FOLDER_PREFIX,\n parsePrefixedName,\n REGION_FOLDER_PREFIX,\n SPACE_FOLDER_PREFIX,\n} from \"./paths.js\";\nimport type {\n AppFolder,\n BrunoCollection,\n BruEnvFile,\n OrgFolder,\n RegionFolder,\n SpaceFolder,\n} from \"./types.js\";\n\nasync function safeReaddir(path: string): Promise<readonly string[]> {\n try {\n const entries = await readdir(path, { withFileTypes: true });\n return entries.filter((e) => e.isDirectory()).map((e) => e.name);\n } catch {\n return [];\n }\n}\n\nasync function listFiles(path: string): Promise<readonly string[]> {\n try {\n const entries = await readdir(path, { withFileTypes: true });\n return entries.filter((e) => e.isFile()).map((e) => e.name);\n } catch {\n return [];\n }\n}\n\nasync function loadEnvFile(path: string, name: string): Promise<BruEnvFile> {\n const raw = await readFile(path, \"utf8\");\n const parsed = parseBruEnvFile(raw);\n return {\n path,\n name: name.replace(/\\.bru$/, \"\"),\n raw,\n vars: parsed.vars,\n secrets: parsed.secrets,\n };\n}\n\nasync function scanAppEnvironments(appPath: string): Promise<readonly BruEnvFile[]> {\n const envDir = join(appPath, ENVIRONMENTS_DIR);\n const files = await listFiles(envDir);\n const bruFiles = files.filter((f) => f.endsWith(\".bru\"));\n const loaded: BruEnvFile[] = [];\n for (const file of bruFiles) {\n loaded.push(await loadEnvFile(join(envDir, file), file));\n }\n return loaded;\n}\n\nasync function scanApp(spacePath: string, name: string): Promise<AppFolder> {\n const appPath = join(spacePath, name);\n const environments = await scanAppEnvironments(appPath);\n return { path: appPath, name, environments };\n}\n\nasync function scanSpace(orgPath: string, dirName: string): Promise<SpaceFolder | undefined> {\n const name = parsePrefixedName(dirName, SPACE_FOLDER_PREFIX);\n if (name === undefined) {\n return undefined;\n }\n const spacePath = join(orgPath, dirName);\n const appDirs = await safeReaddir(spacePath);\n const apps: AppFolder[] = [];\n for (const appDir of appDirs) {\n apps.push(await scanApp(spacePath, appDir));\n }\n return { path: spacePath, name, apps };\n}\n\nasync function scanOrg(regionPath: string, dirName: string): Promise<OrgFolder | undefined> {\n const name = parsePrefixedName(dirName, ORG_FOLDER_PREFIX);\n if (name === undefined) {\n return undefined;\n }\n const orgPath = join(regionPath, dirName);\n const spaceDirs = await safeReaddir(orgPath);\n const spaces: SpaceFolder[] = [];\n for (const spaceDir of spaceDirs) {\n const space = await scanSpace(orgPath, spaceDir);\n if (space) {\n spaces.push(space);\n }\n }\n return { path: orgPath, name, spaces };\n}\n\nasync function scanRegion(root: string, dirName: string): Promise<RegionFolder | undefined> {\n const key = parsePrefixedName(dirName, REGION_FOLDER_PREFIX);\n if (key === undefined) {\n return undefined;\n }\n const regionPath = join(root, dirName);\n const orgDirs = await safeReaddir(regionPath);\n const orgs: OrgFolder[] = [];\n for (const orgDir of orgDirs) {\n const org = await scanOrg(regionPath, orgDir);\n if (org) {\n orgs.push(org);\n }\n }\n return { path: regionPath, key, orgs };\n}\n\nexport async function scanCollection(root: string): Promise<BrunoCollection> {\n const regionDirs = await safeReaddir(root);\n const regions: RegionFolder[] = [];\n for (const dir of regionDirs) {\n const region = await scanRegion(root, dir);\n if (region) {\n regions.push(region);\n }\n }\n return { root, regions };\n}\n\nexport interface ShorthandRef {\n readonly region: string;\n readonly org: string;\n readonly space: string;\n readonly app: string;\n readonly environment?: string;\n readonly filePath?: string;\n}\n\nexport function parseShorthandPath(shorthand: string): ShorthandRef | undefined {\n const cleaned = shorthand.replace(/^[./]+/, \"\").replace(/\\\\/g, \"/\");\n const segs = cleaned.split(\"/\").filter((s) => s.length > 0);\n if (segs.length < 4) {\n return undefined;\n }\n const [region, org, space, app, ...rest] = segs;\n if (!region || !org || !space || !app) {\n return undefined;\n }\n if (rest.length === 0) {\n return { region, org, space, app };\n }\n const filePath = rest.join(\"/\");\n const last = rest[rest.length - 1] ?? \"\";\n const environment = last.endsWith(\".bru\") ? last.replace(/\\.bru$/, \"\") : undefined;\n return environment\n ? { region, org, space, app, environment, filePath }\n : { region, org, space, app, filePath };\n}\n","import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\n\nimport { brunoContextPath } from \"./paths.js\";\nimport type { BrunoContext } from \"./types.js\";\n\nexport async function readContext(): Promise<BrunoContext | undefined> {\n try {\n const raw = await readFile(brunoContextPath(), \"utf8\");\n return JSON.parse(raw) as BrunoContext;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n return undefined;\n }\n throw err;\n }\n}\n\nexport async function writeContext(ctx: Omit<BrunoContext, \"updatedAt\">): Promise<BrunoContext> {\n const updated: BrunoContext = { ...ctx, updatedAt: new Date().toISOString() };\n const path = brunoContextPath();\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, `${JSON.stringify(updated, null, 2)}\\n`, \"utf8\");\n return updated;\n}\n","import { mkdir, readdir, writeFile } from \"node:fs/promises\";\nimport { basename, join } from \"node:path\";\n\nimport type { OrgNode, RegionKey, RegionNode, SpaceNode } from \"@saptools/cf-sync\";\n\nimport type { CfInfoDeps } from \"./cf-info.js\";\nimport { defaultCfInfoDeps, listRegionsWithContent } from \"./cf-info.js\";\nimport { writeCfMetaToFile } from \"./cf-meta.js\";\nimport {\n ENVIRONMENTS_DIR,\n orgFolderName,\n regionFolderName,\n spaceFolderName,\n} from \"./paths.js\";\nimport type { CfAppRef } from \"./types.js\";\n\nexport interface EnvironmentSelection {\n readonly common: readonly string[];\n readonly existing: readonly string[];\n}\n\nexport interface SetupAppPrompts {\n readonly selectRegion: (choices: readonly { value: RegionKey; name: string }[]) => Promise<RegionKey>;\n readonly selectOrg: (choices: readonly { value: string; name: string }[]) => Promise<string>;\n readonly selectSpace: (choices: readonly { value: string; name: string }[]) => Promise<string>;\n readonly selectApp: (choices: readonly { value: string; name: string }[]) => Promise<string>;\n readonly confirmCreate: (path: string) => Promise<boolean>;\n readonly selectEnvironments: (opts: EnvironmentSelection) => Promise<readonly string[]>;\n}\n\nexport interface SetupAppOptions {\n readonly root: string;\n readonly prompts: SetupAppPrompts;\n readonly deps?: CfInfoDeps;\n readonly log?: (msg: string) => void;\n}\n\nexport interface SetupAppResult {\n readonly ref: CfAppRef;\n readonly appPath: string;\n readonly environments: readonly string[];\n readonly created: boolean;\n}\n\nexport const COMMON_ENVIRONMENTS = [\"local\", \"dev\", \"staging\", \"prod\"] as const;\nconst BRUNO_COLLECTION_CONFIG_FILENAME = \"bruno.json\";\n\nexport const ENV_NAME_PATTERN = /^[A-Za-z0-9._-]+$/;\n\nexport function assertValidEnvName(name: string): void {\n if (!ENV_NAME_PATTERN.test(name)) {\n throw new Error(\n `Invalid environment name '${name}': only letters, digits, dot, underscore, and dash are allowed.`,\n );\n }\n}\n\nfunction emptyEnvContent(envName: string, ref: CfAppRef): string {\n const lines = [\n \"vars {\",\n ` __cf_region: ${ref.region}`,\n ` __cf_org: ${ref.org}`,\n ` __cf_space: ${ref.space}`,\n ` __cf_app: ${ref.app}`,\n ` environment: ${envName}`,\n \" baseUrl: \",\n \"}\",\n \"\",\n ];\n return lines.join(\"\\n\");\n}\n\nfunction normalizeCollectionName(root: string): string {\n const candidate = basename(root).replace(/^\\.+/, \"\").trim();\n return candidate.length > 0 ? candidate : \"bruno-collection\";\n}\n\nfunction defaultBrunoConfig(root: string): string {\n return `${JSON.stringify(\n {\n version: \"1\",\n name: normalizeCollectionName(root),\n type: \"collection\",\n ignore: [\"node_modules\", \".git\"],\n },\n null,\n 2,\n )}\\n`;\n}\n\nasync function ensureCollectionConfig(root: string): Promise<void> {\n const filePath = join(root, BRUNO_COLLECTION_CONFIG_FILENAME);\n try {\n await writeFile(filePath, defaultBrunoConfig(root), { encoding: \"utf8\", flag: \"wx\" });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== \"EEXIST\") {\n throw err;\n }\n }\n}\n\nasync function ensureEnvFile(appPath: string, envName: string, ref: CfAppRef): Promise<string> {\n const envDir = join(appPath, ENVIRONMENTS_DIR);\n await mkdir(envDir, { recursive: true });\n const filePath = join(envDir, `${envName}.bru`);\n try {\n await writeFile(filePath, emptyEnvContent(envName, ref), { encoding: \"utf8\", flag: \"wx\" });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== \"EEXIST\") {\n throw err;\n }\n await writeCfMetaToFile(filePath, ref);\n }\n return filePath;\n}\n\nfunction pickRegion(regions: readonly { key: RegionKey; label: string; orgCount: number }[]): readonly {\n readonly value: RegionKey;\n readonly name: string;\n}[] {\n return regions.map((r) => ({ value: r.key, name: `${r.key} — ${r.label} (${r.orgCount.toString()} org${r.orgCount === 1 ? \"\" : \"s\"})` }));\n}\n\nfunction pickOrg(region: RegionNode): readonly { value: string; name: string }[] {\n return region.orgs.map((o) => ({ value: o.name, name: `${o.name} (${o.spaces.length.toString()} space${o.spaces.length === 1 ? \"\" : \"s\"})` }));\n}\n\nfunction pickSpace(org: OrgNode): readonly { value: string; name: string }[] {\n return org.spaces.map((s) => ({ value: s.name, name: `${s.name} (${s.apps.length.toString()} app${s.apps.length === 1 ? \"\" : \"s\"})` }));\n}\n\nfunction pickApp(space: SpaceNode): readonly { value: string; name: string }[] {\n return space.apps.map((a) => ({ value: a.name, name: a.name }));\n}\n\nexport async function setupApp(options: SetupAppOptions): Promise<SetupAppResult> {\n const deps = options.deps ?? defaultCfInfoDeps;\n const log = options.log ?? ((): void => undefined);\n\n const regions = await listRegionsWithContent(deps);\n if (regions.length === 0) {\n throw new Error(\"No CF regions with orgs are cached. Run `cf-sync sync` first.\");\n }\n\n const regionKey = await options.prompts.selectRegion(pickRegion(regions));\n const regionView = await deps.readRegionView(regionKey);\n if (!regionView) {\n throw new Error(`Region ${regionKey} is not cached. Run \\`cf-sync region ${regionKey}\\` or \\`cf-sync sync\\` first.`);\n }\n const region = regionView.region;\n\n if (region.orgs.length === 0) {\n throw new Error(`Region ${regionKey} has no accessible orgs.`);\n }\n\n const orgName = await options.prompts.selectOrg(pickOrg(region));\n const org = region.orgs.find((o) => o.name === orgName);\n if (!org) {\n throw new Error(`Org ${orgName} not found in region ${regionKey}`);\n }\n if (org.spaces.length === 0) {\n throw new Error(`Org ${orgName} has no spaces.`);\n }\n\n const spaceName = await options.prompts.selectSpace(pickSpace(org));\n const space = org.spaces.find((s) => s.name === spaceName);\n if (!space) {\n throw new Error(`Space ${spaceName} not found in org ${orgName}`);\n }\n if (space.apps.length === 0) {\n throw new Error(`Space ${spaceName} has no apps.`);\n }\n\n const appName = await options.prompts.selectApp(pickApp(space));\n const ref: CfAppRef = { region: regionKey, org: orgName, space: spaceName, app: appName };\n\n const appPath = join(\n options.root,\n regionFolderName(regionKey),\n orgFolderName(orgName),\n spaceFolderName(spaceName),\n appName,\n );\n\n const confirmed = await options.prompts.confirmCreate(appPath);\n if (!confirmed) {\n return { ref, appPath, environments: [], created: false };\n }\n\n await mkdir(appPath, { recursive: true });\n await ensureCollectionConfig(appPath);\n\n const existingEnvs = await listExistingEnvs(appPath);\n const common = [...COMMON_ENVIRONMENTS];\n const selected = await options.prompts.selectEnvironments({ common, existing: existingEnvs });\n const merged: string[] = [];\n for (const name of selected) {\n const trimmed = name.trim();\n if (trimmed.length === 0 || merged.includes(trimmed)) {\n continue;\n }\n assertValidEnvName(trimmed);\n merged.push(trimmed);\n }\n if (merged.length === 0) {\n throw new Error(\"At least one environment is required.\");\n }\n\n const created: string[] = [];\n for (const envName of merged) {\n const path = await ensureEnvFile(appPath, envName, ref);\n created.push(path);\n log(`• ${path}`);\n }\n\n return { ref, appPath, environments: created, created: true };\n}\n\nasync function listExistingEnvs(appPath: string): Promise<readonly string[]> {\n try {\n const entries = await readdir(join(appPath, ENVIRONMENTS_DIR), { withFileTypes: true });\n return entries\n .filter((e) => e.isFile() && e.name.endsWith(\".bru\"))\n .map((e) => e.name.replace(/\\.bru$/, \"\"));\n } catch {\n return [];\n }\n}\n","import { spawn } from \"node:child_process\";\nimport { readFile, stat, writeFile } from \"node:fs/promises\";\nimport { createRequire } from \"node:module\";\nimport { delimiter, dirname, isAbsolute, join, relative, resolve, sep } from \"node:path\";\n\nimport type { AppRef } from \"@saptools/cf-xsuaa\";\nimport { getTokenCached as getTokenCachedApi } from \"@saptools/cf-xsuaa\";\n\nimport { upsertVars } from \"./bru-writer.js\";\nimport { readCfMetaFromFile } from \"./cf-meta.js\";\nimport type { ShorthandRef } from \"./folder-scan.js\";\nimport { parseShorthandPath, scanCollection } from \"./folder-scan.js\";\nimport {\n ENVIRONMENTS_DIR,\n orgFolderName,\n regionFolderName,\n spaceFolderName,\n} from \"./paths.js\";\n\nexport type GetTokenCachedFn = (ref: AppRef) => Promise<string>;\n\nexport interface RunSpawnResult {\n readonly code: number;\n readonly stdout: string;\n readonly stderr: string;\n}\n\nexport type SpawnBruFn = (\n args: readonly string[],\n env: NodeJS.ProcessEnv,\n cwd: string,\n) => Promise<RunSpawnResult>;\n\nexport interface RunOptions {\n readonly root: string;\n readonly target: string;\n readonly environment?: string;\n readonly extraArgs?: readonly string[];\n readonly getTokenCached?: GetTokenCachedFn;\n readonly spawnBru?: SpawnBruFn;\n readonly log?: (msg: string) => void;\n}\n\nexport interface RunPlan {\n readonly filePath: string;\n readonly environment: string;\n readonly envFile: string;\n readonly meta: { readonly region: string; readonly org: string; readonly space: string; readonly app: string };\n readonly token: string;\n readonly bruArgs: readonly string[];\n readonly cwd: string;\n}\n\nexport interface RunResult extends RunPlan {\n readonly code: number;\n readonly stdout: string;\n readonly stderr: string;\n}\n\nconst require = createRequire(import.meta.url);\n\nexport interface BruRuntime {\n readonly command: string;\n readonly argsPrefix: readonly string[];\n}\n\nexport interface ResolveBruRuntimeDeps {\n readonly findOnPath?: (command: string, env: NodeJS.ProcessEnv) => Promise<string | undefined>;\n readonly readTextFile?: (path: string) => Promise<string>;\n readonly resolvePackageJsonPath?: () => string;\n}\n\nfunction pathEntries(env: NodeJS.ProcessEnv): readonly string[] {\n const value = env[\"PATH\"] ?? process.env[\"PATH\"] ?? \"\";\n return value.split(delimiter).filter((entry) => entry.length > 0);\n}\n\nfunction pathCandidates(command: string, env: NodeJS.ProcessEnv): readonly string[] {\n if (process.platform !== \"win32\" || command.includes(\".\")) {\n return [command];\n }\n const pathExt =\n env[\"PATHEXT\"]?.split(\";\").filter((entry) => entry.length > 0) ?? [\".COM\", \".EXE\", \".BAT\", \".CMD\"];\n return [command, ...pathExt.map((ext) => `${command}${ext}`)];\n}\n\nasync function findCommandOnPath(command: string, env: NodeJS.ProcessEnv): Promise<string | undefined> {\n const candidates = pathCandidates(command, env);\n for (const entry of pathEntries(env)) {\n for (const candidate of candidates) {\n const fullPath = join(entry, candidate);\n if (await exists(fullPath)) {\n return fullPath;\n }\n }\n }\n return undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction bruBinRelativePath(value: unknown): string | undefined {\n if (!isRecord(value)) {\n return undefined;\n }\n const bin = value[\"bin\"];\n if (typeof bin === \"string\") {\n return bin;\n }\n if (!isRecord(bin)) {\n return undefined;\n }\n const bru = bin[\"bru\"];\n return typeof bru === \"string\" ? bru : undefined;\n}\n\nfunction defaultResolvePackageJsonPath(): string {\n return require.resolve(\"@usebruno/cli/package.json\");\n}\n\nasync function defaultReadTextFile(path: string): Promise<string> {\n return await readFile(path, \"utf8\");\n}\n\nasync function resolveBundledBruBinPath(\n deps: ResolveBruRuntimeDeps,\n): Promise<string | undefined> {\n try {\n const packageJsonPath = (deps.resolvePackageJsonPath ?? defaultResolvePackageJsonPath)();\n const raw = await (deps.readTextFile ?? defaultReadTextFile)(packageJsonPath);\n const binPath = bruBinRelativePath(JSON.parse(raw) as unknown);\n if (!binPath) {\n return undefined;\n }\n return resolve(dirname(packageJsonPath), binPath);\n } catch {\n return undefined;\n }\n}\n\nexport async function resolveBruRuntime(\n env: NodeJS.ProcessEnv = process.env,\n deps: ResolveBruRuntimeDeps = {},\n): Promise<BruRuntime> {\n const onPath = await (deps.findOnPath ?? findCommandOnPath)(\"bru\", env);\n if (onPath) {\n return { command: onPath, argsPrefix: [] };\n }\n const bundledBin = await resolveBundledBruBinPath(deps);\n if (bundledBin) {\n return { command: process.execPath, argsPrefix: [bundledBin] };\n }\n throw new Error(\n \"Unable to find Bruno CLI. Install @usebruno/cli or ensure `bru` is available on PATH.\",\n );\n}\n\nasync function defaultSpawnBru(\n args: readonly string[],\n env: NodeJS.ProcessEnv,\n cwd: string,\n): Promise<RunSpawnResult> {\n const runtime = await resolveBruRuntime(env);\n return await new Promise((resolvePromise, rejectPromise) => {\n const child = spawn(runtime.command, [...runtime.argsPrefix, ...args], { cwd, env, stdio: \"pipe\" });\n let stdout = \"\";\n let stderr = \"\";\n child.stdout.on(\"data\", (chunk: Buffer) => {\n stdout += chunk.toString(\"utf8\");\n process.stdout.write(chunk);\n });\n child.stderr.on(\"data\", (chunk: Buffer) => {\n stderr += chunk.toString(\"utf8\");\n process.stderr.write(chunk);\n });\n child.on(\"error\", rejectPromise);\n child.on(\"close\", (code) => {\n resolvePromise({ code: code ?? 0, stdout, stderr });\n });\n });\n}\n\nasync function exists(path: string): Promise<boolean> {\n try {\n await stat(path);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function resolveTarget(\n root: string,\n target: string,\n): Promise<{ readonly filePath: string; readonly shorthand: ShorthandRef | undefined }> {\n const direct = isAbsolute(target) ? target : resolve(process.cwd(), target);\n if (await exists(direct)) {\n return { filePath: direct, shorthand: undefined };\n }\n\n const shorthand = parseShorthandPath(target);\n if (!shorthand) {\n throw new Error(`Target not found: ${target}`);\n }\n\n const { region, org, space, app, filePath } = shorthand;\n const appDir = join(\n root,\n regionFolderName(region),\n orgFolderName(org),\n spaceFolderName(space),\n app,\n );\n\n if (!filePath) {\n return { filePath: appDir, shorthand };\n }\n\n const candidate = join(appDir, filePath);\n if (await exists(candidate)) {\n return { filePath: candidate, shorthand };\n }\n\n const withExt = candidate.endsWith(\".bru\") ? candidate : `${candidate}.bru`;\n if (await exists(withExt)) {\n return { filePath: withExt, shorthand };\n }\n\n throw new Error(`File not found: ${candidate}`);\n}\n\nasync function chooseEnvironmentFile(\n appDir: string,\n environment: string | undefined,\n): Promise<{ readonly envFile: string; readonly environment: string }> {\n if (environment) {\n const envFile = join(appDir, ENVIRONMENTS_DIR, `${environment}.bru`);\n if (!(await exists(envFile))) {\n throw new Error(`Environment file not found: ${envFile}`);\n }\n return { envFile, environment };\n }\n\n const collection = await scanCollection(resolve(appDir, \"..\", \"..\", \"..\", \"..\"));\n for (const region of collection.regions) {\n for (const org of region.orgs) {\n for (const space of org.spaces) {\n for (const app of space.apps) {\n if (app.path === appDir && app.environments.length > 0) {\n const first = app.environments[0];\n if (first) {\n return { envFile: first.path, environment: first.name };\n }\n }\n }\n }\n }\n }\n throw new Error(`No environment files found under ${appDir}/${ENVIRONMENTS_DIR}`);\n}\n\nfunction findAppDirFromFile(filePath: string, root: string): string {\n const rel = relative(root, filePath).split(sep);\n if (rel.length < 4) {\n throw new Error(`File is not inside a CF-structured bruno collection: ${filePath}`);\n }\n const [regionDir, orgDir, spaceDir, appDir] = rel;\n if (!regionDir || !orgDir || !spaceDir || !appDir) {\n throw new Error(`File is not inside a CF-structured bruno collection: ${filePath}`);\n }\n return join(root, regionDir, orgDir, spaceDir, appDir);\n}\n\nasync function persistAccessToken(envFile: string, token: string): Promise<void> {\n const raw = await readFile(envFile, \"utf8\");\n const { content, changed } = upsertVars(raw, new Map([[\"accessToken\", token]]));\n if (changed) {\n await writeFile(envFile, content, \"utf8\");\n }\n}\n\nexport async function buildRunPlan(options: RunOptions): Promise<RunPlan> {\n const { filePath } = await resolveTarget(options.root, options.target);\n const stats = await stat(filePath);\n\n let appDir: string;\n let requestFile: string | undefined;\n\n if (stats.isDirectory()) {\n appDir = filePath;\n requestFile = undefined;\n } else {\n appDir = findAppDirFromFile(filePath, options.root);\n requestFile = filePath;\n }\n\n const { envFile, environment } = await chooseEnvironmentFile(appDir, options.environment);\n\n const meta = await readCfMetaFromFile(envFile);\n if (!meta) {\n throw new Error(\n `Missing __cf_region/__cf_org/__cf_space/__cf_app in ${envFile}. Run \\`saptools-bruno setup-app\\` first.`,\n );\n }\n\n const getToken = options.getTokenCached ?? getTokenCachedApi;\n const token = await getToken(meta);\n await persistAccessToken(envFile, token);\n\n const bruArgs: string[] = [\"run\"];\n if (requestFile) {\n bruArgs.push(relative(appDir, requestFile) || \".\");\n }\n bruArgs.push(\"--env\", environment, \"--env-var\", `accessToken=${token}`);\n if (options.extraArgs) {\n bruArgs.push(...options.extraArgs);\n }\n\n return {\n filePath,\n environment,\n envFile,\n meta,\n token,\n bruArgs,\n cwd: appDir,\n };\n}\n\nexport async function runBruno(options: RunOptions): Promise<RunResult> {\n const plan = await buildRunPlan(options);\n const spawnFn = options.spawnBru ?? defaultSpawnBru;\n const env: NodeJS.ProcessEnv = { ...process.env, SAPTOOLS_ACCESS_TOKEN: plan.token };\n options.log?.(`▶ bru ${plan.bruArgs.join(\" \")} (cwd=${plan.cwd})`);\n const result = await spawnFn(plan.bruArgs, env, plan.cwd);\n return { ...plan, ...result };\n}\n","import type { CfInfoDeps } from \"./cf-info.js\";\nimport { isValidRegionKey, resolveRef } from \"./cf-info.js\";\nimport { writeContext } from \"./context.js\";\nimport type { BrunoContext } from \"./types.js\";\n\nexport function parseContextShorthand(shorthand: string): {\n readonly region: string;\n readonly org: string;\n readonly space: string;\n readonly app: string;\n} | undefined {\n const segs = shorthand.split(\"/\").filter((s) => s.length > 0);\n if (segs.length !== 4) {\n return undefined;\n }\n const [region, org, space, app] = segs;\n if (!region || !org || !space || !app) {\n return undefined;\n }\n return { region, org, space, app };\n}\n\nexport interface UseOptions {\n readonly shorthand: string;\n readonly deps?: CfInfoDeps;\n readonly verify?: boolean;\n}\n\nexport async function useContext(options: UseOptions): Promise<BrunoContext> {\n const parsed = parseContextShorthand(options.shorthand);\n if (!parsed) {\n throw new Error(\n `Invalid context shorthand: ${options.shorthand}. Expected <region>/<org>/<space>/<app>.`,\n );\n }\n\n if (!isValidRegionKey(parsed.region)) {\n throw new Error(`Unknown region key: ${parsed.region}`);\n }\n\n if (options.verify !== false) {\n const resolved = await resolveRef({ ...parsed, region: parsed.region }, options.deps);\n if (!resolved) {\n throw new Error(\n `Could not verify ${options.shorthand} against the cached CF structure. Run \\`cf-sync sync\\` first.`,\n );\n }\n }\n\n return await writeContext(parsed);\n}\n"],"mappings":"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","names":["sep","readFile","join","readFile","join","readFile","writeFile","readFile","writeFile","mkdir","readdir","writeFile","join","join","writeFile","mkdir","readdir","readFile","writeFile","dirname","join","require","join","readFile","dirname","writeFile"]}
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/bruno/parser.ts","../src/bruno/writer.ts","../src/cf/info.ts","../src/cf/meta.ts","../src/collection/folder-scan.ts","../src/collection/paths.ts","../src/commands/run.ts","../src/commands/setup-app.ts","../src/state/context.ts","../src/commands/use.ts"],"sourcesContent":["import type { RegionKey } from \"@saptools/cf-sync\";\n\nexport interface CfAppRef {\n readonly region: RegionKey;\n readonly org: string;\n readonly space: string;\n readonly app: string;\n}\n\nexport interface BruVarsBlock {\n readonly entries: ReadonlyMap<string, string>;\n}\n\nexport interface BruEnvFile {\n readonly path: string;\n readonly name: string;\n readonly raw: string;\n readonly vars: BruVarsBlock;\n readonly secrets: readonly string[];\n}\n\nexport interface AppFolder {\n readonly path: string;\n readonly name: string;\n readonly environments: readonly BruEnvFile[];\n}\n\nexport interface SpaceFolder {\n readonly path: string;\n readonly name: string;\n readonly apps: readonly AppFolder[];\n}\n\nexport interface OrgFolder {\n readonly path: string;\n readonly name: string;\n readonly spaces: readonly SpaceFolder[];\n}\n\nexport interface RegionFolder {\n readonly path: string;\n readonly key: string;\n readonly orgs: readonly OrgFolder[];\n}\n\nexport interface BrunoCollection {\n readonly root: string;\n readonly regions: readonly RegionFolder[];\n}\n\nexport interface BrunoContext {\n readonly region: string;\n readonly org: string;\n readonly space: string;\n readonly app: string;\n readonly updatedAt: string;\n}\n\nexport interface CfRoute {\n readonly url: string;\n}\n\nexport const CF_META_KEYS = [\"__cf_region\", \"__cf_org\", \"__cf_space\", \"__cf_app\"] as const;\nexport type CfMetaKey = (typeof CF_META_KEYS)[number];\n","import type { BruVarsBlock } from \"../types.js\";\n\ninterface BlockRange {\n readonly header: string;\n readonly start: number;\n readonly end: number;\n readonly bodyStart: number;\n readonly bodyEnd: number;\n readonly open: \"{\" | \"[\";\n readonly close: \"}\" | \"]\";\n}\n\nconst HEADER_REGEX = /(^|\\n)[^\\S\\n]*([a-zA-Z][a-zA-Z0-9:_-]*)[^\\S\\n]*([{[])/g;\n\nfunction findMatchingClose(raw: string, open: \"{\" | \"[\", openIdx: number): number {\n const close = open === \"{\" ? \"}\" : \"]\";\n let depth = 1;\n let i = openIdx + 1;\n while (i < raw.length) {\n const ch = raw[i];\n if (ch === open) {\n depth++;\n } else if (ch === close) {\n depth--;\n if (depth === 0) {\n return i;\n }\n }\n i++;\n }\n return -1;\n}\n\nexport function listBlocks(raw: string): readonly BlockRange[] {\n const blocks: BlockRange[] = [];\n HEADER_REGEX.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = HEADER_REGEX.exec(raw)) !== null) {\n const leadingNewline = match[1] ?? \"\";\n const header = match[2];\n const open = match[3];\n if (header === undefined || (open !== \"{\" && open !== \"[\")) {\n continue;\n }\n const headerStart = match.index + leadingNewline.length;\n const openIdx = match.index + match[0].length - 1;\n const closeIdx = findMatchingClose(raw, open, openIdx);\n if (closeIdx === -1) {\n continue;\n }\n blocks.push({\n header,\n start: headerStart,\n end: closeIdx + 1,\n bodyStart: openIdx + 1,\n bodyEnd: closeIdx,\n open,\n close: open === \"{\" ? \"}\" : \"]\",\n });\n }\n return blocks;\n}\n\nexport function parseKeyValueBody(body: string): Map<string, string> {\n const entries = new Map<string, string>();\n for (const lineRaw of body.split(\"\\n\")) {\n const line = lineRaw.trim();\n if (line.length === 0 || line.startsWith(\"//\")) {\n continue;\n }\n const colon = line.indexOf(\":\");\n if (colon === -1) {\n continue;\n }\n const key = line.slice(0, colon).trim();\n const value = line.slice(colon + 1).trim();\n if (key.length > 0) {\n entries.set(key, value);\n }\n }\n return entries;\n}\n\nexport function parseListBody(body: string): string[] {\n const items: string[] = [];\n for (const lineRaw of body.split(\"\\n\")) {\n const line = lineRaw.trim();\n if (line.length === 0 || line.startsWith(\"//\")) {\n continue;\n }\n items.push(line);\n }\n return items;\n}\n\nexport interface ParsedBruEnv {\n readonly vars: BruVarsBlock;\n readonly secrets: readonly string[];\n}\n\nexport function parseBruEnvFile(raw: string): ParsedBruEnv {\n const blocks = listBlocks(raw);\n const varsBlock = blocks.find((b) => b.header === \"vars\" && b.open === \"{\");\n const secretsBlock = blocks.find((b) => b.header === \"vars:secret\" && b.open === \"[\");\n\n const entries = varsBlock\n ? parseKeyValueBody(raw.slice(varsBlock.bodyStart, varsBlock.bodyEnd))\n : new Map<string, string>();\n const secrets = secretsBlock\n ? parseListBody(raw.slice(secretsBlock.bodyStart, secretsBlock.bodyEnd))\n : [];\n\n return { vars: { entries }, secrets };\n}\n","import { listBlocks, parseKeyValueBody } from \"./parser.js\";\n\nexport interface UpsertResult {\n readonly content: string;\n readonly changed: boolean;\n}\n\nfunction formatVarsBlock(entries: ReadonlyMap<string, string>): string {\n const lines: string[] = [];\n for (const [key, value] of entries) {\n lines.push(` ${key}: ${value}`);\n }\n return lines.join(\"\\n\");\n}\n\nexport function upsertVars(\n raw: string,\n updates: ReadonlyMap<string, string>,\n): UpsertResult {\n const blocks = listBlocks(raw);\n const varsBlock = blocks.find((b) => b.header === \"vars\" && b.open === \"{\");\n\n if (!varsBlock) {\n const newBlock = `vars {\\n${formatVarsBlock(updates)}\\n}\\n`;\n const sep = raw.length > 0 && !raw.endsWith(\"\\n\") ? \"\\n\\n\" : raw.length > 0 ? \"\\n\" : \"\";\n return { content: `${raw}${sep}${newBlock}`, changed: updates.size > 0 };\n }\n\n const body = raw.slice(varsBlock.bodyStart, varsBlock.bodyEnd);\n const existing = parseKeyValueBody(body);\n let changed = false;\n for (const [k, v] of updates) {\n if (existing.get(k) !== v) {\n existing.set(k, v);\n changed = true;\n }\n }\n\n if (!changed) {\n return { content: raw, changed: false };\n }\n\n const rebuilt = `\\n${formatVarsBlock(existing)}\\n`;\n const before = raw.slice(0, varsBlock.bodyStart);\n const after = raw.slice(varsBlock.bodyEnd);\n return { content: `${before}${rebuilt}${after}`, changed: true };\n}\n\nexport function ensureSecretEntry(raw: string, secretName: string): UpsertResult {\n const blocks = listBlocks(raw);\n const secretsBlock = blocks.find((b) => b.header === \"vars:secret\" && b.open === \"[\");\n\n if (!secretsBlock) {\n const newBlock = `vars:secret [\\n ${secretName}\\n]\\n`;\n const sep = raw.length > 0 && !raw.endsWith(\"\\n\") ? \"\\n\\n\" : raw.length > 0 ? \"\\n\" : \"\";\n return { content: `${raw}${sep}${newBlock}`, changed: true };\n }\n\n const body = raw.slice(secretsBlock.bodyStart, secretsBlock.bodyEnd);\n const items = body\n .split(\"\\n\")\n .map((l) => l.trim())\n .filter((l) => l.length > 0 && !l.startsWith(\"//\"));\n if (items.includes(secretName)) {\n return { content: raw, changed: false };\n }\n items.push(secretName);\n const rebuilt = `\\n ${items.join(\"\\n \")}\\n`;\n const before = raw.slice(0, secretsBlock.bodyStart);\n const after = raw.slice(secretsBlock.bodyEnd);\n return { content: `${before}${rebuilt}${after}`, changed: true };\n}\n","import type {\n CfStructure,\n OrgNode,\n RegionKey,\n RegionNode,\n RegionsView,\n RegionView,\n SpaceNode,\n StructureView,\n} from \"@saptools/cf-sync\";\nimport {\n getRegionView as getRegionViewApi,\n readRegionsView,\n readRegionView,\n readStructureView,\n REGION_KEYS,\n} from \"@saptools/cf-sync\";\n\nexport interface CfInfoDeps {\n readonly readStructureView: () => Promise<StructureView | undefined>;\n readonly readRegionsView: () => Promise<RegionsView>;\n readonly readRegionView: (key: RegionKey) => Promise<RegionView | undefined>;\n readonly getRegionView: (opts: {\n readonly regionKey: RegionKey;\n readonly email?: string;\n readonly password?: string;\n readonly refreshIfMissing?: boolean;\n }) => Promise<RegionView | undefined>;\n}\n\nexport const defaultCfInfoDeps: CfInfoDeps = {\n readStructureView,\n readRegionsView,\n readRegionView,\n getRegionView: getRegionViewApi,\n};\n\nexport function isValidRegionKey(value: string): value is RegionKey {\n return (REGION_KEYS as readonly string[]).includes(value);\n}\n\nexport interface StructureSnapshot {\n readonly source: \"runtime\" | \"stable\" | \"empty\";\n readonly structure: CfStructure | undefined;\n readonly stale: boolean;\n readonly message: string | undefined;\n}\n\nexport async function getStructureSnapshot(\n deps: CfInfoDeps = defaultCfInfoDeps,\n): Promise<StructureSnapshot> {\n const view = await deps.readStructureView();\n if (!view) {\n return {\n source: \"empty\",\n structure: undefined,\n stale: true,\n message: \"No CF structure cached. Run `cf-sync sync` first.\",\n };\n }\n\n const stale = view.source === \"runtime\" && view.metadata?.status === \"running\";\n return {\n source: view.source,\n structure: view.structure,\n stale,\n message: stale ? \"A CF sync is still running — showing partial data.\" : undefined,\n };\n}\n\nexport interface RegionSuggestion {\n readonly key: RegionKey;\n readonly label: string;\n readonly orgCount: number;\n}\n\nexport async function listRegionsWithContent(\n deps: CfInfoDeps = defaultCfInfoDeps,\n): Promise<readonly RegionSuggestion[]> {\n const snapshot = await getStructureSnapshot(deps);\n if (!snapshot.structure) {\n return [];\n }\n return snapshot.structure.regions\n .filter((r) => r.accessible && r.orgs.length > 0)\n .map((r) => ({ key: r.key, label: r.label, orgCount: r.orgs.length }));\n}\n\nexport async function getRegion(\n key: RegionKey,\n deps: CfInfoDeps = defaultCfInfoDeps,\n): Promise<RegionNode | undefined> {\n const view = await deps.readRegionView(key);\n return view?.region;\n}\n\nexport function findOrg(region: RegionNode, orgName: string): OrgNode | undefined {\n return region.orgs.find((o) => o.name === orgName);\n}\n\nexport function findSpace(org: OrgNode, spaceName: string): SpaceNode | undefined {\n return org.spaces.find((s) => s.name === spaceName);\n}\n\nexport function findApp(space: SpaceNode, appName: string): { readonly name: string } | undefined {\n return space.apps.find((a) => a.name === appName);\n}\n\nexport interface ResolvedRef {\n readonly region: RegionNode;\n readonly org: OrgNode;\n readonly space: SpaceNode;\n readonly app: { readonly name: string };\n}\n\nexport async function resolveRef(\n ref: {\n readonly region: RegionKey;\n readonly org: string;\n readonly space: string;\n readonly app: string;\n },\n deps: CfInfoDeps = defaultCfInfoDeps,\n): Promise<ResolvedRef | undefined> {\n const region = await getRegion(ref.region, deps);\n if (!region) {\n return undefined;\n }\n const org = findOrg(region, ref.org);\n if (!org) {\n return undefined;\n }\n const space = findSpace(org, ref.space);\n if (!space) {\n return undefined;\n }\n const app = findApp(space, ref.app);\n if (!app) {\n return undefined;\n }\n return { region, org, space, app };\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\n\nimport { parseBruEnvFile } from \"../bruno/parser.js\";\nimport { upsertVars } from \"../bruno/writer.js\";\nimport { CF_META_KEYS } from \"../types.js\";\nimport type { CfAppRef, CfMetaKey } from \"../types.js\";\n\nexport interface CfMeta {\n readonly region: string;\n readonly org: string;\n readonly space: string;\n readonly app: string;\n}\n\nexport function readCfMetaFromVars(vars: ReadonlyMap<string, string>): CfMeta | undefined {\n const region = vars.get(\"__cf_region\");\n const org = vars.get(\"__cf_org\");\n const space = vars.get(\"__cf_space\");\n const app = vars.get(\"__cf_app\");\n if (!region || !org || !space || !app) {\n return undefined;\n }\n return { region, org, space, app };\n}\n\nexport function buildCfMetaUpdates(ref: CfAppRef, baseUrl?: string): Map<string, string> {\n const updates = new Map<string, string>();\n const pairs: readonly [CfMetaKey, string][] = [\n [\"__cf_region\", ref.region],\n [\"__cf_org\", ref.org],\n [\"__cf_space\", ref.space],\n [\"__cf_app\", ref.app],\n ];\n for (const [k, v] of pairs) {\n updates.set(k, v);\n }\n if (baseUrl !== undefined) {\n updates.set(\"baseUrl\", baseUrl);\n }\n return updates;\n}\n\nexport function hasCfMeta(vars: ReadonlyMap<string, string>): boolean {\n return CF_META_KEYS.every((k) => {\n const v = vars.get(k);\n return v !== undefined && v.length > 0;\n });\n}\n\nexport async function readCfMetaFromFile(path: string): Promise<CfMeta | undefined> {\n const raw = await readFile(path, \"utf8\");\n const parsed = parseBruEnvFile(raw);\n return readCfMetaFromVars(parsed.vars.entries);\n}\n\nexport async function writeCfMetaToFile(\n path: string,\n ref: CfAppRef,\n baseUrl?: string,\n): Promise<boolean> {\n const raw = await readFile(path, \"utf8\");\n const updates = buildCfMetaUpdates(ref, baseUrl);\n const { content, changed } = upsertVars(raw, updates);\n if (changed) {\n await writeFile(path, content, \"utf8\");\n }\n return changed;\n}\n","import { readdir, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nimport { parseBruEnvFile } from \"../bruno/parser.js\";\nimport type {\n AppFolder,\n BrunoCollection,\n BruEnvFile,\n OrgFolder,\n RegionFolder,\n SpaceFolder,\n} from \"../types.js\";\n\nimport {\n ENVIRONMENTS_DIR,\n ORG_FOLDER_PREFIX,\n parsePrefixedName,\n REGION_FOLDER_PREFIX,\n SPACE_FOLDER_PREFIX,\n} from \"./paths.js\";\n\nasync function safeReaddir(path: string): Promise<readonly string[]> {\n try {\n const entries = await readdir(path, { withFileTypes: true });\n return entries.filter((e) => e.isDirectory()).map((e) => e.name);\n } catch {\n return [];\n }\n}\n\nasync function listFiles(path: string): Promise<readonly string[]> {\n try {\n const entries = await readdir(path, { withFileTypes: true });\n return entries.filter((e) => e.isFile()).map((e) => e.name);\n } catch {\n return [];\n }\n}\n\nasync function loadEnvFile(path: string, name: string): Promise<BruEnvFile> {\n const raw = await readFile(path, \"utf8\");\n const parsed = parseBruEnvFile(raw);\n return {\n path,\n name: name.replace(/\\.bru$/, \"\"),\n raw,\n vars: parsed.vars,\n secrets: parsed.secrets,\n };\n}\n\nasync function scanAppEnvironments(appPath: string): Promise<readonly BruEnvFile[]> {\n const envDir = join(appPath, ENVIRONMENTS_DIR);\n const files = await listFiles(envDir);\n const bruFiles = files.filter((f) => f.endsWith(\".bru\"));\n const loaded: BruEnvFile[] = [];\n for (const file of bruFiles) {\n loaded.push(await loadEnvFile(join(envDir, file), file));\n }\n return loaded;\n}\n\nasync function scanApp(spacePath: string, name: string): Promise<AppFolder> {\n const appPath = join(spacePath, name);\n const environments = await scanAppEnvironments(appPath);\n return { path: appPath, name, environments };\n}\n\nasync function scanSpace(orgPath: string, dirName: string): Promise<SpaceFolder | undefined> {\n const name = parsePrefixedName(dirName, SPACE_FOLDER_PREFIX);\n if (name === undefined) {\n return undefined;\n }\n const spacePath = join(orgPath, dirName);\n const appDirs = await safeReaddir(spacePath);\n const apps: AppFolder[] = [];\n for (const appDir of appDirs) {\n apps.push(await scanApp(spacePath, appDir));\n }\n return { path: spacePath, name, apps };\n}\n\nasync function scanOrg(regionPath: string, dirName: string): Promise<OrgFolder | undefined> {\n const name = parsePrefixedName(dirName, ORG_FOLDER_PREFIX);\n if (name === undefined) {\n return undefined;\n }\n const orgPath = join(regionPath, dirName);\n const spaceDirs = await safeReaddir(orgPath);\n const spaces: SpaceFolder[] = [];\n for (const spaceDir of spaceDirs) {\n const space = await scanSpace(orgPath, spaceDir);\n if (space) {\n spaces.push(space);\n }\n }\n return { path: orgPath, name, spaces };\n}\n\nasync function scanRegion(root: string, dirName: string): Promise<RegionFolder | undefined> {\n const key = parsePrefixedName(dirName, REGION_FOLDER_PREFIX);\n if (key === undefined) {\n return undefined;\n }\n const regionPath = join(root, dirName);\n const orgDirs = await safeReaddir(regionPath);\n const orgs: OrgFolder[] = [];\n for (const orgDir of orgDirs) {\n const org = await scanOrg(regionPath, orgDir);\n if (org) {\n orgs.push(org);\n }\n }\n return { path: regionPath, key, orgs };\n}\n\nexport async function scanCollection(root: string): Promise<BrunoCollection> {\n const regionDirs = await safeReaddir(root);\n const regions: RegionFolder[] = [];\n for (const dir of regionDirs) {\n const region = await scanRegion(root, dir);\n if (region) {\n regions.push(region);\n }\n }\n return { root, regions };\n}\n\nexport interface ShorthandRef {\n readonly region: string;\n readonly org: string;\n readonly space: string;\n readonly app: string;\n readonly environment?: string;\n readonly filePath?: string;\n}\n\nexport function parseShorthandPath(shorthand: string): ShorthandRef | undefined {\n const cleaned = shorthand.replace(/^[./]+/, \"\").replace(/\\\\/g, \"/\");\n const segs = cleaned.split(\"/\").filter((s) => s.length > 0);\n if (segs.length < 4) {\n return undefined;\n }\n const [region, org, space, app, ...rest] = segs;\n if (!region || !org || !space || !app) {\n return undefined;\n }\n if (rest.length === 0) {\n return { region, org, space, app };\n }\n const filePath = rest.join(\"/\");\n const last = rest[rest.length - 1] ?? \"\";\n const environment = last.endsWith(\".bru\") ? last.replace(/\\.bru$/, \"\") : undefined;\n return environment\n ? { region, org, space, app, environment, filePath }\n : { region, org, space, app, filePath };\n}\n","import { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport const SAPTOOLS_DIR_NAME = \".saptools\";\nexport const BRUNO_CONTEXT_FILENAME = \"bruno-context.json\";\n\nexport const REGION_FOLDER_PREFIX = \"region__\";\nexport const ORG_FOLDER_PREFIX = \"org__\";\nexport const SPACE_FOLDER_PREFIX = \"space__\";\nexport const ENVIRONMENTS_DIR = \"environments\";\n\nexport function saptoolsDir(): string {\n return join(homedir(), SAPTOOLS_DIR_NAME);\n}\n\nexport function brunoContextPath(): string {\n return join(saptoolsDir(), BRUNO_CONTEXT_FILENAME);\n}\n\nexport function regionFolderName(key: string): string {\n return `${REGION_FOLDER_PREFIX}${key}`;\n}\n\nexport function orgFolderName(name: string): string {\n return `${ORG_FOLDER_PREFIX}${name}`;\n}\n\nexport function spaceFolderName(name: string): string {\n return `${SPACE_FOLDER_PREFIX}${name}`;\n}\n\nexport function parsePrefixedName(\n dirName: string,\n prefix: string,\n): string | undefined {\n if (!dirName.startsWith(prefix)) {\n return undefined;\n }\n return dirName.slice(prefix.length);\n}\n","import { spawn } from \"node:child_process\";\nimport { readFile, stat, writeFile } from \"node:fs/promises\";\nimport { createRequire } from \"node:module\";\nimport { delimiter, dirname, isAbsolute, join, relative, resolve, sep } from \"node:path\";\n\nimport type { AppRef } from \"@saptools/cf-xsuaa\";\nimport { getTokenCached as getTokenCachedApi } from \"@saptools/cf-xsuaa\";\n\nimport { upsertVars } from \"../bruno/writer.js\";\nimport { readCfMetaFromFile } from \"../cf/meta.js\";\nimport type { ShorthandRef } from \"../collection/folder-scan.js\";\nimport { parseShorthandPath, scanCollection } from \"../collection/folder-scan.js\";\nimport {\n ENVIRONMENTS_DIR,\n orgFolderName,\n regionFolderName,\n spaceFolderName,\n} from \"../collection/paths.js\";\n\nexport type GetTokenCachedFn = (ref: AppRef) => Promise<string>;\n\nexport interface RunSpawnResult {\n readonly code: number;\n readonly stdout: string;\n readonly stderr: string;\n}\n\nexport type SpawnBruFn = (\n args: readonly string[],\n env: NodeJS.ProcessEnv,\n cwd: string,\n) => Promise<RunSpawnResult>;\n\nexport interface RunOptions {\n readonly root: string;\n readonly target: string;\n readonly environment?: string;\n readonly extraArgs?: readonly string[];\n readonly getTokenCached?: GetTokenCachedFn;\n readonly spawnBru?: SpawnBruFn;\n readonly log?: (msg: string) => void;\n}\n\nexport interface RunPlan {\n readonly filePath: string;\n readonly environment: string;\n readonly envFile: string;\n readonly meta: { readonly region: string; readonly org: string; readonly space: string; readonly app: string };\n readonly token: string;\n readonly bruArgs: readonly string[];\n readonly cwd: string;\n}\n\nexport interface RunResult extends RunPlan {\n readonly code: number;\n readonly stdout: string;\n readonly stderr: string;\n}\n\nconst require = createRequire(import.meta.url);\n\nexport interface BruRuntime {\n readonly command: string;\n readonly argsPrefix: readonly string[];\n}\n\nexport interface ResolveBruRuntimeDeps {\n readonly findOnPath?: (command: string, env: NodeJS.ProcessEnv) => Promise<string | undefined>;\n readonly readTextFile?: (path: string) => Promise<string>;\n readonly resolvePackageJsonPath?: () => string;\n}\n\nfunction pathEntries(env: NodeJS.ProcessEnv): readonly string[] {\n const value = env[\"PATH\"] ?? process.env[\"PATH\"] ?? \"\";\n return value.split(delimiter).filter((entry) => entry.length > 0);\n}\n\nfunction pathCandidates(command: string, env: NodeJS.ProcessEnv): readonly string[] {\n if (process.platform !== \"win32\" || command.includes(\".\")) {\n return [command];\n }\n const pathExt =\n env[\"PATHEXT\"]?.split(\";\").filter((entry) => entry.length > 0) ?? [\".COM\", \".EXE\", \".BAT\", \".CMD\"];\n return [command, ...pathExt.map((ext) => `${command}${ext}`)];\n}\n\nasync function findCommandOnPath(command: string, env: NodeJS.ProcessEnv): Promise<string | undefined> {\n const candidates = pathCandidates(command, env);\n for (const entry of pathEntries(env)) {\n for (const candidate of candidates) {\n const fullPath = join(entry, candidate);\n if (await exists(fullPath)) {\n return fullPath;\n }\n }\n }\n return undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction bruBinRelativePath(value: unknown): string | undefined {\n if (!isRecord(value)) {\n return undefined;\n }\n const bin = value[\"bin\"];\n if (typeof bin === \"string\") {\n return bin;\n }\n if (!isRecord(bin)) {\n return undefined;\n }\n const bru = bin[\"bru\"];\n return typeof bru === \"string\" ? bru : undefined;\n}\n\nfunction defaultResolvePackageJsonPath(): string {\n return require.resolve(\"@usebruno/cli/package.json\");\n}\n\nasync function defaultReadTextFile(path: string): Promise<string> {\n return await readFile(path, \"utf8\");\n}\n\nasync function resolveBundledBruBinPath(\n deps: ResolveBruRuntimeDeps,\n): Promise<string | undefined> {\n try {\n const packageJsonPath = (deps.resolvePackageJsonPath ?? defaultResolvePackageJsonPath)();\n const raw = await (deps.readTextFile ?? defaultReadTextFile)(packageJsonPath);\n const binPath = bruBinRelativePath(JSON.parse(raw) as unknown);\n if (!binPath) {\n return undefined;\n }\n return resolve(dirname(packageJsonPath), binPath);\n } catch {\n return undefined;\n }\n}\n\nexport async function resolveBruRuntime(\n env: NodeJS.ProcessEnv = process.env,\n deps: ResolveBruRuntimeDeps = {},\n): Promise<BruRuntime> {\n const onPath = await (deps.findOnPath ?? findCommandOnPath)(\"bru\", env);\n if (onPath) {\n return { command: onPath, argsPrefix: [] };\n }\n const bundledBin = await resolveBundledBruBinPath(deps);\n if (bundledBin) {\n return { command: process.execPath, argsPrefix: [bundledBin] };\n }\n throw new Error(\n \"Unable to find Bruno CLI. Install @usebruno/cli or ensure `bru` is available on PATH.\",\n );\n}\n\nasync function defaultSpawnBru(\n args: readonly string[],\n env: NodeJS.ProcessEnv,\n cwd: string,\n): Promise<RunSpawnResult> {\n const runtime = await resolveBruRuntime(env);\n return await new Promise((resolvePromise, rejectPromise) => {\n const child = spawn(runtime.command, [...runtime.argsPrefix, ...args], { cwd, env, stdio: \"pipe\" });\n let stdout = \"\";\n let stderr = \"\";\n child.stdout.on(\"data\", (chunk: Buffer) => {\n stdout += chunk.toString(\"utf8\");\n process.stdout.write(chunk);\n });\n child.stderr.on(\"data\", (chunk: Buffer) => {\n stderr += chunk.toString(\"utf8\");\n process.stderr.write(chunk);\n });\n child.on(\"error\", rejectPromise);\n child.on(\"close\", (code) => {\n resolvePromise({ code: code ?? 0, stdout, stderr });\n });\n });\n}\n\nasync function exists(path: string): Promise<boolean> {\n try {\n await stat(path);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function resolveTarget(\n root: string,\n target: string,\n): Promise<{ readonly filePath: string; readonly shorthand: ShorthandRef | undefined }> {\n const direct = isAbsolute(target) ? target : resolve(process.cwd(), target);\n if (await exists(direct)) {\n return { filePath: direct, shorthand: undefined };\n }\n\n const shorthand = parseShorthandPath(target);\n if (!shorthand) {\n throw new Error(`Target not found: ${target}`);\n }\n\n const { region, org, space, app, filePath } = shorthand;\n const appDir = join(\n root,\n regionFolderName(region),\n orgFolderName(org),\n spaceFolderName(space),\n app,\n );\n\n if (!filePath) {\n return { filePath: appDir, shorthand };\n }\n\n const candidate = join(appDir, filePath);\n if (await exists(candidate)) {\n return { filePath: candidate, shorthand };\n }\n\n const withExt = candidate.endsWith(\".bru\") ? candidate : `${candidate}.bru`;\n if (await exists(withExt)) {\n return { filePath: withExt, shorthand };\n }\n\n throw new Error(`File not found: ${candidate}`);\n}\n\nasync function chooseEnvironmentFile(\n appDir: string,\n environment: string | undefined,\n): Promise<{ readonly envFile: string; readonly environment: string }> {\n if (environment) {\n const envFile = join(appDir, ENVIRONMENTS_DIR, `${environment}.bru`);\n if (!(await exists(envFile))) {\n throw new Error(`Environment file not found: ${envFile}`);\n }\n return { envFile, environment };\n }\n\n const collection = await scanCollection(resolve(appDir, \"..\", \"..\", \"..\", \"..\"));\n for (const region of collection.regions) {\n for (const org of region.orgs) {\n for (const space of org.spaces) {\n for (const app of space.apps) {\n if (app.path === appDir && app.environments.length > 0) {\n const first = app.environments[0];\n if (first) {\n return { envFile: first.path, environment: first.name };\n }\n }\n }\n }\n }\n }\n throw new Error(`No environment files found under ${appDir}/${ENVIRONMENTS_DIR}`);\n}\n\nfunction findAppDirFromFile(filePath: string, root: string): string {\n const rel = relative(root, filePath).split(sep);\n if (rel.length < 4) {\n throw new Error(`File is not inside a CF-structured bruno collection: ${filePath}`);\n }\n const [regionDir, orgDir, spaceDir, appDir] = rel;\n if (!regionDir || !orgDir || !spaceDir || !appDir) {\n throw new Error(`File is not inside a CF-structured bruno collection: ${filePath}`);\n }\n return join(root, regionDir, orgDir, spaceDir, appDir);\n}\n\nasync function persistAccessToken(envFile: string, token: string): Promise<void> {\n const raw = await readFile(envFile, \"utf8\");\n const { content, changed } = upsertVars(raw, new Map([[\"accessToken\", token]]));\n if (changed) {\n await writeFile(envFile, content, \"utf8\");\n }\n}\n\nexport async function buildRunPlan(options: RunOptions): Promise<RunPlan> {\n const { filePath } = await resolveTarget(options.root, options.target);\n const stats = await stat(filePath);\n\n let appDir: string;\n let requestFile: string | undefined;\n\n if (stats.isDirectory()) {\n appDir = filePath;\n requestFile = undefined;\n } else {\n appDir = findAppDirFromFile(filePath, options.root);\n requestFile = filePath;\n }\n\n const { envFile, environment } = await chooseEnvironmentFile(appDir, options.environment);\n\n const meta = await readCfMetaFromFile(envFile);\n if (!meta) {\n throw new Error(\n `Missing __cf_region/__cf_org/__cf_space/__cf_app in ${envFile}. Run \\`saptools-bruno setup-app\\` first.`,\n );\n }\n\n const getToken = options.getTokenCached ?? getTokenCachedApi;\n const token = await getToken(meta);\n await persistAccessToken(envFile, token);\n\n const bruArgs: string[] = [\"run\"];\n if (requestFile) {\n bruArgs.push(relative(appDir, requestFile) || \".\");\n }\n bruArgs.push(\"--env\", environment, \"--env-var\", `accessToken=${token}`);\n if (options.extraArgs) {\n bruArgs.push(...options.extraArgs);\n }\n\n return {\n filePath,\n environment,\n envFile,\n meta,\n token,\n bruArgs,\n cwd: appDir,\n };\n}\n\nexport async function runBruno(options: RunOptions): Promise<RunResult> {\n const plan = await buildRunPlan(options);\n const spawnFn = options.spawnBru ?? defaultSpawnBru;\n const env: NodeJS.ProcessEnv = { ...process.env, SAPTOOLS_ACCESS_TOKEN: plan.token };\n options.log?.(`▶ bru ${plan.bruArgs.join(\" \")} (cwd=${plan.cwd})`);\n const result = await spawnFn(plan.bruArgs, env, plan.cwd);\n return { ...plan, ...result };\n}\n","import { mkdir, readdir, writeFile } from \"node:fs/promises\";\nimport { basename, join } from \"node:path\";\n\nimport type { OrgNode, RegionKey, RegionNode, SpaceNode } from \"@saptools/cf-sync\";\n\nimport type { CfInfoDeps } from \"../cf/info.js\";\nimport { defaultCfInfoDeps, listRegionsWithContent } from \"../cf/info.js\";\nimport { writeCfMetaToFile } from \"../cf/meta.js\";\nimport {\n ENVIRONMENTS_DIR,\n orgFolderName,\n regionFolderName,\n spaceFolderName,\n} from \"../collection/paths.js\";\nimport type { CfAppRef } from \"../types.js\";\n\nexport interface EnvironmentSelection {\n readonly common: readonly string[];\n readonly existing: readonly string[];\n}\n\nexport interface SetupAppPrompts {\n readonly selectRegion: (choices: readonly { value: RegionKey; name: string }[]) => Promise<RegionKey>;\n readonly selectOrg: (choices: readonly { value: string; name: string }[]) => Promise<string>;\n readonly selectSpace: (choices: readonly { value: string; name: string }[]) => Promise<string>;\n readonly selectApp: (choices: readonly { value: string; name: string }[]) => Promise<string>;\n readonly confirmCreate: (path: string) => Promise<boolean>;\n readonly selectEnvironments: (opts: EnvironmentSelection) => Promise<readonly string[]>;\n}\n\nexport interface SetupAppOptions {\n readonly root: string;\n readonly prompts: SetupAppPrompts;\n readonly deps?: CfInfoDeps;\n readonly log?: (msg: string) => void;\n}\n\nexport interface SetupAppResult {\n readonly ref: CfAppRef;\n readonly appPath: string;\n readonly environments: readonly string[];\n readonly created: boolean;\n}\n\nexport const COMMON_ENVIRONMENTS = [\"local\", \"dev\", \"staging\", \"prod\"] as const;\nconst BRUNO_COLLECTION_CONFIG_FILENAME = \"bruno.json\";\n\nexport const ENV_NAME_PATTERN = /^[A-Za-z0-9._-]+$/;\n\nexport function assertValidEnvName(name: string): void {\n if (!ENV_NAME_PATTERN.test(name)) {\n throw new Error(\n `Invalid environment name '${name}': only letters, digits, dot, underscore, and dash are allowed.`,\n );\n }\n}\n\nfunction emptyEnvContent(envName: string, ref: CfAppRef): string {\n const lines = [\n \"vars {\",\n ` __cf_region: ${ref.region}`,\n ` __cf_org: ${ref.org}`,\n ` __cf_space: ${ref.space}`,\n ` __cf_app: ${ref.app}`,\n ` environment: ${envName}`,\n \" baseUrl: \",\n \"}\",\n \"\",\n ];\n return lines.join(\"\\n\");\n}\n\nfunction normalizeCollectionName(root: string): string {\n const candidate = basename(root).replace(/^\\.+/, \"\").trim();\n return candidate.length > 0 ? candidate : \"bruno-collection\";\n}\n\nfunction defaultBrunoConfig(root: string): string {\n return `${JSON.stringify(\n {\n version: \"1\",\n name: normalizeCollectionName(root),\n type: \"collection\",\n ignore: [\"node_modules\", \".git\"],\n },\n null,\n 2,\n )}\\n`;\n}\n\nasync function ensureCollectionConfig(root: string): Promise<void> {\n const filePath = join(root, BRUNO_COLLECTION_CONFIG_FILENAME);\n try {\n await writeFile(filePath, defaultBrunoConfig(root), { encoding: \"utf8\", flag: \"wx\" });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== \"EEXIST\") {\n throw err;\n }\n }\n}\n\nasync function ensureEnvFile(appPath: string, envName: string, ref: CfAppRef): Promise<string> {\n const envDir = join(appPath, ENVIRONMENTS_DIR);\n await mkdir(envDir, { recursive: true });\n const filePath = join(envDir, `${envName}.bru`);\n try {\n await writeFile(filePath, emptyEnvContent(envName, ref), { encoding: \"utf8\", flag: \"wx\" });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== \"EEXIST\") {\n throw err;\n }\n await writeCfMetaToFile(filePath, ref);\n }\n return filePath;\n}\n\nfunction pickRegion(regions: readonly { key: RegionKey; label: string; orgCount: number }[]): readonly {\n readonly value: RegionKey;\n readonly name: string;\n}[] {\n return regions.map((r) => ({ value: r.key, name: `${r.key} — ${r.label} (${r.orgCount.toString()} org${r.orgCount === 1 ? \"\" : \"s\"})` }));\n}\n\nfunction pickOrg(region: RegionNode): readonly { value: string; name: string }[] {\n return region.orgs.map((o) => ({ value: o.name, name: `${o.name} (${o.spaces.length.toString()} space${o.spaces.length === 1 ? \"\" : \"s\"})` }));\n}\n\nfunction pickSpace(org: OrgNode): readonly { value: string; name: string }[] {\n return org.spaces.map((s) => ({ value: s.name, name: `${s.name} (${s.apps.length.toString()} app${s.apps.length === 1 ? \"\" : \"s\"})` }));\n}\n\nfunction pickApp(space: SpaceNode): readonly { value: string; name: string }[] {\n return space.apps.map((a) => ({ value: a.name, name: a.name }));\n}\n\nexport async function setupApp(options: SetupAppOptions): Promise<SetupAppResult> {\n const deps = options.deps ?? defaultCfInfoDeps;\n const log = options.log ?? ((): void => undefined);\n\n const regions = await listRegionsWithContent(deps);\n if (regions.length === 0) {\n throw new Error(\"No CF regions with orgs are cached. Run `cf-sync sync` first.\");\n }\n\n const regionKey = await options.prompts.selectRegion(pickRegion(regions));\n const regionView = await deps.readRegionView(regionKey);\n if (!regionView) {\n throw new Error(`Region ${regionKey} is not cached. Run \\`cf-sync region ${regionKey}\\` or \\`cf-sync sync\\` first.`);\n }\n const region = regionView.region;\n\n if (region.orgs.length === 0) {\n throw new Error(`Region ${regionKey} has no accessible orgs.`);\n }\n\n const orgName = await options.prompts.selectOrg(pickOrg(region));\n const org = region.orgs.find((o) => o.name === orgName);\n if (!org) {\n throw new Error(`Org ${orgName} not found in region ${regionKey}`);\n }\n if (org.spaces.length === 0) {\n throw new Error(`Org ${orgName} has no spaces.`);\n }\n\n const spaceName = await options.prompts.selectSpace(pickSpace(org));\n const space = org.spaces.find((s) => s.name === spaceName);\n if (!space) {\n throw new Error(`Space ${spaceName} not found in org ${orgName}`);\n }\n if (space.apps.length === 0) {\n throw new Error(`Space ${spaceName} has no apps.`);\n }\n\n const appName = await options.prompts.selectApp(pickApp(space));\n const ref: CfAppRef = { region: regionKey, org: orgName, space: spaceName, app: appName };\n\n const appPath = join(\n options.root,\n regionFolderName(regionKey),\n orgFolderName(orgName),\n spaceFolderName(spaceName),\n appName,\n );\n\n const confirmed = await options.prompts.confirmCreate(appPath);\n if (!confirmed) {\n return { ref, appPath, environments: [], created: false };\n }\n\n await mkdir(appPath, { recursive: true });\n await ensureCollectionConfig(appPath);\n\n const existingEnvs = await listExistingEnvs(appPath);\n const common = [...COMMON_ENVIRONMENTS];\n const selected = await options.prompts.selectEnvironments({ common, existing: existingEnvs });\n const merged: string[] = [];\n for (const name of selected) {\n const trimmed = name.trim();\n if (trimmed.length === 0 || merged.includes(trimmed)) {\n continue;\n }\n assertValidEnvName(trimmed);\n merged.push(trimmed);\n }\n if (merged.length === 0) {\n throw new Error(\"At least one environment is required.\");\n }\n\n const created: string[] = [];\n for (const envName of merged) {\n const path = await ensureEnvFile(appPath, envName, ref);\n created.push(path);\n log(`• ${path}`);\n }\n\n return { ref, appPath, environments: created, created: true };\n}\n\nasync function listExistingEnvs(appPath: string): Promise<readonly string[]> {\n try {\n const entries = await readdir(join(appPath, ENVIRONMENTS_DIR), { withFileTypes: true });\n return entries\n .filter((e) => e.isFile() && e.name.endsWith(\".bru\"))\n .map((e) => e.name.replace(/\\.bru$/, \"\"));\n } catch {\n return [];\n }\n}\n","import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\n\nimport { brunoContextPath } from \"../collection/paths.js\";\nimport type { BrunoContext } from \"../types.js\";\n\nexport async function readContext(): Promise<BrunoContext | undefined> {\n try {\n const raw = await readFile(brunoContextPath(), \"utf8\");\n return JSON.parse(raw) as BrunoContext;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n return undefined;\n }\n throw err;\n }\n}\n\nexport async function writeContext(ctx: Omit<BrunoContext, \"updatedAt\">): Promise<BrunoContext> {\n const updated: BrunoContext = { ...ctx, updatedAt: new Date().toISOString() };\n const path = brunoContextPath();\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, `${JSON.stringify(updated, null, 2)}\\n`, \"utf8\");\n return updated;\n}\n","import type { CfInfoDeps } from \"../cf/info.js\";\nimport { isValidRegionKey, resolveRef } from \"../cf/info.js\";\nimport { writeContext } from \"../state/context.js\";\nimport type { BrunoContext } from \"../types.js\";\n\nexport function parseContextShorthand(shorthand: string): {\n readonly region: string;\n readonly org: string;\n readonly space: string;\n readonly app: string;\n} | undefined {\n const segs = shorthand.split(\"/\").filter((s) => s.length > 0);\n if (segs.length !== 4) {\n return undefined;\n }\n const [region, org, space, app] = segs;\n if (!region || !org || !space || !app) {\n return undefined;\n }\n return { region, org, space, app };\n}\n\nexport interface UseOptions {\n readonly shorthand: string;\n readonly deps?: CfInfoDeps;\n readonly verify?: boolean;\n}\n\nexport async function useContext(options: UseOptions): Promise<BrunoContext> {\n const parsed = parseContextShorthand(options.shorthand);\n if (!parsed) {\n throw new Error(\n `Invalid context shorthand: ${options.shorthand}. Expected <region>/<org>/<space>/<app>.`,\n );\n }\n\n if (!isValidRegionKey(parsed.region)) {\n throw new Error(`Unknown region key: ${parsed.region}`);\n }\n\n if (options.verify !== false) {\n const resolved = await resolveRef({ ...parsed, region: parsed.region }, options.deps);\n if (!resolved) {\n throw new Error(\n `Could not verify ${options.shorthand} against the cached CF structure. Run \\`cf-sync sync\\` first.`,\n );\n }\n }\n\n return await writeContext(parsed);\n}\n"],"mappings":"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","names":["sep","readFile","join","readFile","join","readFile","writeFile","join","require","join","readFile","writeFile","readdir","writeFile","join","join","writeFile","readdir","mkdir","readFile","writeFile","dirname","readFile","mkdir","dirname","writeFile"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saptools/bruno",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Smart runner for Bruno — CF-aware env metadata, automatic token injection, and shorthand paths",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@inquirer/prompts": "^8.3.2",
|
|
54
|
-
"@saptools/cf-sync": "^0.
|
|
54
|
+
"@saptools/cf-sync": "^0.4.1",
|
|
55
55
|
"@saptools/cf-xsuaa": "^0.1.6",
|
|
56
56
|
"@usebruno/cli": "^3.2.2",
|
|
57
57
|
"commander": "^13.0.0"
|