@ebay-dt/bonfire-node 0.2.0-alpha.0 → 0.2.0-alpha.11
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 +18 -5
- package/dist/deployment-provider.d.ts +2 -1
- package/dist/deployment-provider.d.ts.map +1 -1
- package/dist/deployment-provider.js +2 -1
- package/dist/deployment-provider.js.map +1 -1
- package/dist/duplicate.d.ts.map +1 -1
- package/dist/duplicate.js +103 -47
- package/dist/duplicate.js.map +1 -1
- package/dist/git-repository.d.ts +16 -1
- package/dist/git-repository.d.ts.map +1 -1
- package/dist/git-repository.js +127 -1
- package/dist/git-repository.js.map +1 -1
- package/dist/github-cli.d.ts.map +1 -1
- package/dist/github-cli.js +3 -1
- package/dist/github-cli.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/prototype-templates.d.ts +0 -1
- package/dist/internal/prototype-templates.d.ts.map +1 -1
- package/dist/internal/prototype-templates.js +0 -5
- package/dist/internal/prototype-templates.js.map +1 -1
- package/dist/lifecycle/deployment-worktree.d.ts +36 -0
- package/dist/lifecycle/deployment-worktree.d.ts.map +1 -0
- package/dist/lifecycle/deployment-worktree.js +503 -0
- package/dist/lifecycle/deployment-worktree.js.map +1 -0
- package/dist/lifecycle/local-prototype-lifecycle.d.ts +15 -1
- package/dist/lifecycle/local-prototype-lifecycle.d.ts.map +1 -1
- package/dist/lifecycle/local-prototype-lifecycle.js +738 -98
- package/dist/lifecycle/local-prototype-lifecycle.js.map +1 -1
- package/dist/lifecycle/preparation-marker.d.ts +12 -0
- package/dist/lifecycle/preparation-marker.d.ts.map +1 -0
- package/dist/lifecycle/preparation-marker.js +76 -0
- package/dist/lifecycle/preparation-marker.js.map +1 -0
- package/dist/lifecycle/prototype-path-policy.d.ts +18 -0
- package/dist/lifecycle/prototype-path-policy.d.ts.map +1 -0
- package/dist/lifecycle/prototype-path-policy.js +429 -0
- package/dist/lifecycle/prototype-path-policy.js.map +1 -0
- package/dist/lifecycle/repository-summary.d.ts +7 -1
- package/dist/lifecycle/repository-summary.d.ts.map +1 -1
- package/dist/lifecycle/repository-summary.js +20 -4
- package/dist/lifecycle/repository-summary.js.map +1 -1
- package/dist/lifecycle/repository-synchronization.d.ts +13 -8
- package/dist/lifecycle/repository-synchronization.d.ts.map +1 -1
- package/dist/lifecycle/repository-synchronization.js +680 -139
- package/dist/lifecycle/repository-synchronization.js.map +1 -1
- package/dist/lifecycle/runtime-context.d.ts +2 -0
- package/dist/lifecycle/runtime-context.d.ts.map +1 -1
- package/dist/lifecycle/runtime-context.js +5 -1
- package/dist/lifecycle/runtime-context.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git-repository.js","sourceRoot":"","sources":["../src/git-repository.ts"],"names":[],"mappings":"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","sourcesContent":["import { isAbsolute } from \"node:path\";\nimport { simpleGit } from \"simple-git\";\nimport {\n asFailure,\n isNonEmptyString,\n isPositiveInteger,\n isRecord,\n} from \"./internal/utils.js\";\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\nconst DEFAULT_MAX_CONCURRENT_PROCESSES = 1;\nconst DEFAULT_COMMIT_IDENTITY = {\n name: \"Bonfire\",\n email: \"bonfire@localhost\",\n};\nconst NOTHING_TO_COMMIT_MESSAGES = [\n \"nothing to commit\",\n \"nothing added to commit\",\n];\n\nexport type GitCommitIdentity = {\n name: string;\n email: string;\n};\n\nexport type GitRepositoryOptions = {\n repositoryRoot: string;\n timeoutMs?: number;\n maxConcurrentProcesses?: number;\n commitIdentity?: GitCommitIdentity;\n};\n\nexport type GitStatusFile = {\n path: string;\n index: string;\n workingDirectory: string;\n from?: string;\n};\n\nexport type GitStatusSnapshot = {\n current: string | null;\n files: readonly GitStatusFile[];\n clean: boolean;\n};\n\nexport type GitRemoteSnapshot = {\n name: string;\n fetchUrl: string | null;\n pushUrl: string | null;\n};\n\nexport type GitBranchSnapshot = {\n current: string | null;\n all: readonly string[];\n};\n\nexport type GitCommitSnapshot = {\n branch: string;\n commit: string;\n root: boolean;\n};\n\nexport type GitCommitResult = GitCommitSnapshot | null;\n\nexport type GitPushResult = {\n remoteStatus: \"pushed\" | \"local-only\";\n};\n\nexport type GitRepositoryErrorKind =\n | \"missing-git\"\n | \"timeout\"\n | \"conflict\"\n | \"command-failure\"\n | \"malformed-output\"\n | \"invalid-configuration\"\n | \"unexpected\";\n\nexport class GitRepositoryError extends Error {\n readonly kind: GitRepositoryErrorKind;\n readonly operation: string;\n\n constructor(kind: GitRepositoryErrorKind, operation: string) {\n super(`Git operation failed: ${operation}`);\n this.name = \"GitRepositoryError\";\n this.kind = kind;\n this.operation = operation;\n }\n}\n\nexport interface GitRepository {\n readonly repositoryRoot: string;\n currentBranch(): Promise<string>;\n status(pathspecs?: readonly string[]): Promise<GitStatusSnapshot>;\n remotes(): Promise<readonly GitRemoteSnapshot[]>;\n branches(): Promise<GitBranchSnapshot>;\n fetch(remote: string, branch?: string): Promise<void>;\n checkout(args: readonly string[]): Promise<void>;\n checkoutLocalBranch(branch: string): Promise<void>;\n merge(args: readonly string[]): Promise<void>;\n add(pathspecs: readonly string[]): Promise<void>;\n commit(\n message: string,\n pathspecs?: readonly string[],\n ): Promise<GitCommitResult>;\n push(\n remote: string,\n branch: string,\n options?: readonly string[],\n ): Promise<void>;\n restore(pathspecs: readonly string[]): Promise<void>;\n clean(mode: string, pathspecs: readonly string[]): Promise<void>;\n raw(args: readonly string[]): Promise<string>;\n}\n\nfunction classifyError(error: unknown): GitRepositoryErrorKind {\n if (error instanceof GitRepositoryError) return error.kind;\n\n const failure = asFailure(error);\n const message = typeof failure.message === \"string\" ? failure.message : \"\";\n const normalized = message.toLowerCase();\n\n if (failure.code === \"ENOENT\" || normalized.includes(\"enoent\")) {\n return \"missing-git\";\n }\n\n if (\n failure.code === \"ETIMEDOUT\" ||\n failure.killed === true ||\n failure.signal === \"SIGTERM\" ||\n normalized.includes(\"timed out\") ||\n normalized.includes(\"timeout\")\n ) {\n return \"timeout\";\n }\n\n if (\n normalized.includes(\"conflict\") ||\n normalized.includes(\"would be overwritten\") ||\n normalized.includes(\"unmerged paths\")\n ) {\n return \"conflict\";\n }\n\n if (isRecord(error) || error instanceof Error) return \"command-failure\";\n return \"unexpected\";\n}\n\nfunction normalizeError(operation: string, error: unknown) {\n if (error instanceof GitRepositoryError) return error;\n return new GitRepositoryError(classifyError(error), operation);\n}\n\nfunction assertValidPositiveInteger(value: number, option: string) {\n if (!isPositiveInteger(value)) {\n throw new GitRepositoryError(\"invalid-configuration\", option);\n }\n}\n\nfunction assertValidBranchName(value: string, option: string) {\n if (\n !isNonEmptyString(value) ||\n value.startsWith(\"-\") ||\n value.includes(\"\\0\") ||\n /\\s/u.test(value) ||\n value.includes(\"@{\") ||\n value.split(/[\\\\/]/u).some((segment) => segment === \"..\")\n ) {\n throw new GitRepositoryError(\"invalid-configuration\", option);\n }\n}\n\nfunction assertValidPathspec(pathspec: string) {\n if (\n !isNonEmptyString(pathspec) ||\n isAbsolute(pathspec) ||\n /^[A-Za-z]:[\\\\/]/u.test(pathspec) ||\n pathspec.startsWith(\"\\\\\") ||\n pathspec.startsWith(\"-\") ||\n pathspec.startsWith(\":\") ||\n pathspec.includes(\"\\0\") ||\n pathspec.includes(\"*\") ||\n pathspec.includes(\"?\") ||\n pathspec.includes(\"[\") ||\n pathspec.includes(\"]\") ||\n pathspec === \".\" ||\n pathspec.split(/[\\\\/]/u).some((segment) => segment === \"..\")\n ) {\n throw new GitRepositoryError(\"invalid-configuration\", \"pathspec\");\n }\n}\n\nfunction assertValidPathspecs(pathspecs: readonly string[]) {\n if (pathspecs.length === 0) {\n throw new GitRepositoryError(\"invalid-configuration\", \"pathspec\");\n }\n for (const pathspec of pathspecs) assertValidPathspec(pathspec);\n return [...pathspecs];\n}\n\nfunction assertValidArguments(args: readonly string[], operation: string) {\n if (\n args.some(\n (argument) => !isNonEmptyString(argument) || argument.includes(\"\\0\"),\n )\n ) {\n throw new GitRepositoryError(\"invalid-configuration\", operation);\n }\n return [...args];\n}\n\nfunction isNothingToCommit(error: unknown) {\n const failure = asFailure(error);\n const message = typeof failure.message === \"string\" ? failure.message : \"\";\n return NOTHING_TO_COMMIT_MESSAGES.some((needle) =>\n message.toLowerCase().includes(needle),\n );\n}\n\nclass SimpleGitRepository implements GitRepository {\n readonly repositoryRoot: string;\n readonly #git;\n\n constructor(options: Required<GitRepositoryOptions>) {\n this.repositoryRoot = options.repositoryRoot;\n this.#git = simpleGit(options.repositoryRoot, {\n baseDir: options.repositoryRoot,\n maxConcurrentProcesses: options.maxConcurrentProcesses,\n config: [\n `user.name=${options.commitIdentity.name}`,\n `user.email=${options.commitIdentity.email}`,\n ],\n timeout: { block: options.timeoutMs },\n });\n }\n\n async #execute<Value>(operation: string, action: () => Promise<Value>) {\n try {\n return await action();\n } catch (error) {\n throw normalizeError(operation, error);\n }\n }\n\n async currentBranch() {\n const result = await this.#execute(\"current-branch\", () =>\n this.#git.revparse([\"--abbrev-ref\", \"HEAD\"]),\n );\n if (!isNonEmptyString(result) || result.trim().length === 0) {\n throw new GitRepositoryError(\"malformed-output\", \"current-branch\");\n }\n return result.trim();\n }\n\n async status(pathspecs?: readonly string[]) {\n const validatedPathspecs =\n pathspecs === undefined ? undefined : assertValidPathspecs(pathspecs);\n const result = await this.#execute(\"status\", () =>\n validatedPathspecs === undefined\n ? this.#git.status()\n : this.#git.status([\"--\", ...validatedPathspecs]),\n );\n\n if (\n !isRecord(result) ||\n !Array.isArray(result.files) ||\n (typeof result.current !== \"string\" && result.current !== null) ||\n typeof result.isClean !== \"function\"\n ) {\n throw new GitRepositoryError(\"malformed-output\", \"status\");\n }\n\n const files: GitStatusFile[] = [];\n for (const file of result.files) {\n if (!isRecord(file)) {\n throw new GitRepositoryError(\"malformed-output\", \"status\");\n }\n if (\n typeof file.path !== \"string\" ||\n typeof file.index !== \"string\" ||\n typeof file.working_dir !== \"string\"\n ) {\n throw new GitRepositoryError(\"malformed-output\", \"status\");\n }\n\n files.push({\n path: file.path,\n index: file.index,\n workingDirectory: file.working_dir,\n ...(typeof file.from === \"string\" ? { from: file.from } : {}),\n });\n }\n\n let clean: boolean;\n try {\n clean = result.isClean();\n } catch {\n throw new GitRepositoryError(\"malformed-output\", \"status\");\n }\n if (typeof clean !== \"boolean\") {\n throw new GitRepositoryError(\"malformed-output\", \"status\");\n }\n\n return {\n current: result.current,\n files,\n clean,\n } satisfies GitStatusSnapshot;\n }\n\n async remotes() {\n const result = await this.#execute(\"remotes\", () =>\n this.#git.getRemotes(true),\n );\n if (!Array.isArray(result)) {\n throw new GitRepositoryError(\"malformed-output\", \"remotes\");\n }\n\n const remotes: GitRemoteSnapshot[] = [];\n for (const remote of result) {\n if (!isRecord(remote) || typeof remote.name !== \"string\") {\n throw new GitRepositoryError(\"malformed-output\", \"remotes\");\n }\n const refs = remote.refs;\n if (!isRecord(refs)) {\n throw new GitRepositoryError(\"malformed-output\", \"remotes\");\n }\n if (typeof refs.fetch !== \"string\" || typeof refs.push !== \"string\") {\n throw new GitRepositoryError(\"malformed-output\", \"remotes\");\n }\n\n remotes.push({\n name: remote.name,\n fetchUrl: refs.fetch,\n pushUrl: refs.push,\n });\n }\n return remotes;\n }\n\n async branches() {\n const result = await this.#execute(\"branches\", () =>\n this.#git.branch([\"-a\"]),\n );\n if (\n !isRecord(result) ||\n !Array.isArray(result.all) ||\n (typeof result.current !== \"string\" && result.current !== null) ||\n !result.all.every((branch) => typeof branch === \"string\")\n ) {\n throw new GitRepositoryError(\"malformed-output\", \"branches\");\n }\n\n return {\n current: result.current,\n all: [...result.all],\n } satisfies GitBranchSnapshot;\n }\n\n async fetch(remote: string, branch?: string) {\n assertValidBranchName(remote, \"remote\");\n if (branch !== undefined) assertValidBranchName(branch, \"branch\");\n await this.#execute(\"fetch\", () =>\n branch === undefined\n ? this.#git.fetch(remote)\n : this.#git.fetch(remote, branch),\n );\n }\n\n async checkout(args: readonly string[]) {\n const validatedArgs = assertValidArguments(args, \"checkout\");\n await this.#execute(\"checkout\", () => this.#git.checkout(validatedArgs));\n }\n\n async checkoutLocalBranch(branch: string) {\n assertValidBranchName(branch, \"branch\");\n await this.#execute(\"checkout-local-branch\", () =>\n this.#git.checkoutLocalBranch(branch),\n );\n }\n\n async merge(args: readonly string[]) {\n const validatedArgs = assertValidArguments(args, \"merge\");\n await this.#execute(\"merge\", () => this.#git.merge(validatedArgs));\n }\n\n async add(pathspecs: readonly string[]) {\n const validatedPathspecs = assertValidPathspecs(pathspecs);\n await this.#execute(\"add\", () => this.#git.add(validatedPathspecs));\n }\n\n async commit(message: string, pathspecs?: readonly string[]) {\n if (!isNonEmptyString(message)) {\n throw new GitRepositoryError(\"invalid-configuration\", \"commit-message\");\n }\n const validatedPathspecs =\n pathspecs === undefined ? undefined : assertValidPathspecs(pathspecs);\n\n let result: unknown;\n try {\n result =\n validatedPathspecs === undefined\n ? await this.#git.commit(message)\n : await this.#git.commit(message, [...validatedPathspecs]);\n } catch (error) {\n if (isNothingToCommit(error)) return null;\n throw normalizeError(\"commit\", error);\n }\n if (\n !isRecord(result) ||\n typeof result.branch !== \"string\" ||\n typeof result.commit !== \"string\" ||\n typeof result.root !== \"boolean\"\n ) {\n throw new GitRepositoryError(\"malformed-output\", \"commit\");\n }\n\n return {\n branch: result.branch,\n commit: result.commit,\n root: result.root,\n } satisfies GitCommitSnapshot;\n }\n\n async push(remote: string, branch: string, options: readonly string[] = []) {\n assertValidBranchName(remote, \"remote\");\n assertValidBranchName(branch, \"branch\");\n const validatedOptions = assertValidArguments(options, \"push\");\n await this.#execute(\"push\", () =>\n this.#git.push(remote, branch, validatedOptions),\n );\n }\n\n async restore(pathspecs: readonly string[]) {\n const validatedPathspecs = assertValidPathspecs(pathspecs);\n await this.#execute(\"restore\", () =>\n this.#git.checkout([\"--\", ...validatedPathspecs]),\n );\n }\n\n async clean(mode: string, pathspecs: readonly string[]) {\n if (!/^[a-z]+$/u.test(mode)) {\n throw new GitRepositoryError(\"invalid-configuration\", \"clean-mode\");\n }\n const validatedPathspecs = assertValidPathspecs(pathspecs);\n await this.#execute(\"clean\", () =>\n this.#git.clean(mode, validatedPathspecs),\n );\n }\n\n async raw(args: readonly string[]) {\n const validatedArgs = assertValidArguments(args, \"raw\");\n const result = await this.#execute(\"raw\", () =>\n this.#git.raw(validatedArgs),\n );\n if (typeof result !== \"string\") {\n throw new GitRepositoryError(\"malformed-output\", \"raw\");\n }\n return result;\n }\n}\n\nexport type PrepareIdentityBranchOptions = {\n identityBranch: string;\n primaryBranch: string;\n remote: string;\n};\n\nexport async function prepareIdentityBranch(\n repository: GitRepository,\n options: PrepareIdentityBranchOptions,\n): Promise<void> {\n assertValidBranchName(options.identityBranch, \"identity-branch\");\n assertValidBranchName(options.primaryBranch, \"primary-branch\");\n assertValidBranchName(options.remote, \"remote\");\n\n const currentBranch = await repository.currentBranch();\n if (currentBranch === options.identityBranch) return;\n\n const status = await repository.status();\n if (!status.clean) {\n throw new GitRepositoryError(\"conflict\", \"prepare-identity-branch\");\n }\n\n const remotes = await repository.remotes();\n const configuredRemote = remotes.some(\n (remote) => remote.name === options.remote,\n );\n if (configuredRemote) {\n await repository.fetch(options.remote, options.primaryBranch);\n }\n\n const branches = await repository.branches();\n const hasLocalPrimary = branches.all.includes(options.primaryBranch);\n const remotePrimary = `remotes/${options.remote}/${options.primaryBranch}`;\n const hasRemotePrimary =\n configuredRemote && branches.all.includes(remotePrimary);\n if (!hasLocalPrimary && !hasRemotePrimary) {\n throw new GitRepositoryError(\"command-failure\", \"primary-branch\");\n }\n\n if (hasLocalPrimary) {\n await repository.checkout([options.primaryBranch]);\n } else {\n await repository.checkout([\n \"-b\",\n options.primaryBranch,\n \"--track\",\n `${options.remote}/${options.primaryBranch}`,\n ]);\n }\n if (configuredRemote) {\n await repository.merge([\n `${options.remote}/${options.primaryBranch}`,\n \"--ff-only\",\n ]);\n }\n\n if (branches.all.includes(options.identityBranch)) {\n await repository.checkout([options.identityBranch]);\n return;\n }\n\n const remoteBranch = `remotes/${options.remote}/${options.identityBranch}`;\n if (branches.all.includes(remoteBranch)) {\n await repository.checkout([\n \"-b\",\n options.identityBranch,\n \"--track\",\n `${options.remote}/${options.identityBranch}`,\n ]);\n return;\n }\n\n await repository.checkoutLocalBranch(options.identityBranch);\n}\n\nexport async function commitPath(\n repository: GitRepository,\n pathspec: string,\n message: string,\n): Promise<GitCommitResult> {\n const validatedPathspecs = assertValidPathspecs([pathspec]);\n await repository.add(validatedPathspecs);\n return repository.commit(message, validatedPathspecs);\n}\n\nexport async function discardPath(\n repository: GitRepository,\n pathspec: string,\n): Promise<void> {\n const validatedPathspec = assertValidPathspecs([pathspec])[0]!;\n await repository.raw([\"reset\", \"HEAD\", \"--\", validatedPathspec]);\n await repository.restore([validatedPathspec]);\n await repository.clean(\"fd\", [validatedPathspec]);\n}\n\nexport async function pushBranch(\n repository: GitRepository,\n remote: string,\n branch: string,\n): Promise<GitPushResult> {\n assertValidBranchName(remote, \"remote\");\n assertValidBranchName(branch, \"branch\");\n\n const hasRemote = (await repository.remotes()).some(\n (configuredRemote) => configuredRemote.name === remote,\n );\n if (!hasRemote) return { remoteStatus: \"local-only\" };\n\n await repository.push(remote, branch, [\"--set-upstream\"]);\n return { remoteStatus: \"pushed\" };\n}\n\nexport function createGitRepository(\n options: GitRepositoryOptions,\n): GitRepository {\n if (!isAbsolute(options.repositoryRoot)) {\n throw new GitRepositoryError(\"invalid-configuration\", \"repository-root\");\n }\n\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const maxConcurrentProcesses =\n options.maxConcurrentProcesses ?? DEFAULT_MAX_CONCURRENT_PROCESSES;\n const commitIdentity = options.commitIdentity ?? DEFAULT_COMMIT_IDENTITY;\n\n assertValidPositiveInteger(timeoutMs, \"timeout\");\n assertValidPositiveInteger(\n maxConcurrentProcesses,\n \"max-concurrent-processes\",\n );\n\n return new SimpleGitRepository({\n repositoryRoot: options.repositoryRoot,\n timeoutMs,\n maxConcurrentProcesses,\n commitIdentity,\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"git-repository.js","sourceRoot":"","sources":["../src/git-repository.ts"],"names":[],"mappings":"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","sourcesContent":["import { isAbsolute } from \"node:path\";\nimport { simpleGit } from \"simple-git\";\nimport {\n asFailure,\n isNonEmptyString,\n isPositiveInteger,\n isRecord,\n} from \"./internal/utils.js\";\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\nexport const UPLOAD_INACTIVITY_TIMEOUT_MS = 5 * 60_000;\nexport const UPLOAD_WALL_TIMEOUT_MS = 30 * 60_000;\nconst DEFAULT_MAX_CONCURRENT_PROCESSES = 1;\nconst DEFAULT_COMMIT_IDENTITY = {\n name: \"Bonfire\",\n email: \"bonfire@localhost\",\n};\nconst NOTHING_TO_COMMIT_MESSAGES = [\n \"nothing to commit\",\n \"nothing added to commit\",\n];\n\nexport type GitCommitIdentity = {\n name: string;\n email: string;\n};\n\nexport type GitRepositoryOptions = {\n repositoryRoot: string;\n timeoutMs?: number;\n maxConcurrentProcesses?: number;\n commitIdentity?: GitCommitIdentity;\n};\n\nexport type GitStatusFile = {\n path: string;\n index: string;\n workingDirectory: string;\n from?: string;\n};\n\nexport type GitStatusSnapshot = {\n current: string | null;\n files: readonly GitStatusFile[];\n clean: boolean;\n};\n\nexport type GitRemoteSnapshot = {\n name: string;\n fetchUrl: string | null;\n pushUrl: string | null;\n};\n\nexport type GitBranchSnapshot = {\n current: string | null;\n all: readonly string[];\n};\n\nexport type GitCommitSnapshot = {\n branch: string;\n commit: string;\n root: boolean;\n};\n\nexport type GitCommitResult = GitCommitSnapshot | null;\n\nexport type GitPushResult = {\n remoteStatus: \"pushed\" | \"local-only\";\n};\n\nexport type GitUploadProgress = {\n stage: string;\n progress: number;\n processed: number;\n total: number;\n};\n\nexport type GitRepositoryErrorKind =\n | \"missing-git\"\n | \"timeout\"\n | \"conflict\"\n | \"non-fast-forward\"\n | \"command-failure\"\n | \"malformed-output\"\n | \"invalid-configuration\"\n | \"unexpected\";\n\nexport class GitRepositoryError extends Error {\n readonly kind: GitRepositoryErrorKind;\n readonly operation: string;\n\n constructor(kind: GitRepositoryErrorKind, operation: string) {\n super(`Git operation failed: ${operation}`);\n this.name = \"GitRepositoryError\";\n this.kind = kind;\n this.operation = operation;\n }\n}\n\nexport interface GitRepository {\n readonly repositoryRoot: string;\n currentBranch(): Promise<string>;\n status(pathspecs?: readonly string[]): Promise<GitStatusSnapshot>;\n remotes(): Promise<readonly GitRemoteSnapshot[]>;\n branches(): Promise<GitBranchSnapshot>;\n fetch(remote: string, branch?: string): Promise<void>;\n checkout(args: readonly string[]): Promise<void>;\n checkoutLocalBranch(branch: string): Promise<void>;\n merge(args: readonly string[]): Promise<void>;\n add(pathspecs: readonly string[]): Promise<void>;\n commit(\n message: string,\n pathspecs?: readonly string[],\n ): Promise<GitCommitResult>;\n push(\n remote: string,\n branch: string,\n options?: readonly string[],\n ): Promise<void>;\n /** Push using the bounded, upload-specific timeout policy. */\n pushUpload?(\n remote: string,\n branch: string,\n options?: readonly string[],\n onProgress?: (progress: GitUploadProgress) => void,\n ): Promise<void>;\n restore(pathspecs: readonly string[]): Promise<void>;\n clean(mode: string, pathspecs: readonly string[]): Promise<void>;\n raw(args: readonly string[]): Promise<string>;\n /** Execute a read/write Git command with a private environment. */\n rawWithEnv?(\n args: readonly string[],\n environment: Readonly<Record<string, string>>,\n ): Promise<string>;\n}\n\nfunction classifyError(error: unknown): GitRepositoryErrorKind {\n if (error instanceof GitRepositoryError) return error.kind;\n\n const failure = asFailure(error);\n const message = typeof failure.message === \"string\" ? failure.message : \"\";\n const normalized = message.toLowerCase();\n\n if (failure.code === \"ENOENT\" || normalized.includes(\"enoent\")) {\n return \"missing-git\";\n }\n\n if (\n failure.code === \"ETIMEDOUT\" ||\n failure.killed === true ||\n failure.signal === \"SIGTERM\" ||\n normalized.includes(\"timed out\") ||\n normalized.includes(\"timeout\")\n ) {\n return \"timeout\";\n }\n\n if (\n normalized.includes(\"conflict\") ||\n normalized.includes(\"would be overwritten\") ||\n normalized.includes(\"unmerged paths\")\n ) {\n return \"conflict\";\n }\n\n if (\n normalized.includes(\"non-fast-forward\") ||\n normalized.includes(\"fetch first\") ||\n normalized.includes(\"stale info\")\n ) {\n return \"non-fast-forward\";\n }\n\n if (isRecord(error) || error instanceof Error) return \"command-failure\";\n return \"unexpected\";\n}\n\nfunction normalizeError(operation: string, error: unknown) {\n if (error instanceof GitRepositoryError) return error;\n return new GitRepositoryError(classifyError(error), operation);\n}\n\nfunction assertValidPositiveInteger(value: number, option: string) {\n if (!isPositiveInteger(value)) {\n throw new GitRepositoryError(\"invalid-configuration\", option);\n }\n}\n\nfunction assertValidBranchName(value: string, option: string) {\n if (\n !isNonEmptyString(value) ||\n value.startsWith(\"-\") ||\n value.includes(\"\\0\") ||\n /\\s/u.test(value) ||\n value.includes(\"@{\") ||\n value.split(/[\\\\/]/u).some((segment) => segment === \"..\")\n ) {\n throw new GitRepositoryError(\"invalid-configuration\", option);\n }\n}\n\nfunction assertValidPathspec(pathspec: string) {\n if (\n !isNonEmptyString(pathspec) ||\n isAbsolute(pathspec) ||\n /^[A-Za-z]:[\\\\/]/u.test(pathspec) ||\n pathspec.startsWith(\"\\\\\") ||\n pathspec.startsWith(\"-\") ||\n pathspec.startsWith(\":\") ||\n pathspec.includes(\"\\0\") ||\n pathspec.includes(\"*\") ||\n pathspec.includes(\"?\") ||\n pathspec.includes(\"[\") ||\n pathspec.includes(\"]\") ||\n pathspec === \".\" ||\n pathspec.split(/[\\\\/]/u).some((segment) => segment === \"..\")\n ) {\n throw new GitRepositoryError(\"invalid-configuration\", \"pathspec\");\n }\n}\n\nfunction assertValidPathspecs(pathspecs: readonly string[]) {\n if (pathspecs.length === 0) {\n throw new GitRepositoryError(\"invalid-configuration\", \"pathspec\");\n }\n for (const pathspec of pathspecs) assertValidPathspec(pathspec);\n return [...pathspecs];\n}\n\nfunction assertValidArguments(args: readonly string[], operation: string) {\n if (\n args.some(\n (argument) => !isNonEmptyString(argument) || argument.includes(\"\\0\"),\n )\n ) {\n throw new GitRepositoryError(\"invalid-configuration\", operation);\n }\n return [...args];\n}\n\nfunction isNothingToCommit(error: unknown) {\n const failure = asFailure(error);\n const message = typeof failure.message === \"string\" ? failure.message : \"\";\n return NOTHING_TO_COMMIT_MESSAGES.some((needle) =>\n message.toLowerCase().includes(needle),\n );\n}\n\nclass SimpleGitRepository implements GitRepository {\n readonly repositoryRoot: string;\n readonly #git;\n readonly #gitOptions;\n\n constructor(options: Required<GitRepositoryOptions>) {\n this.repositoryRoot = options.repositoryRoot;\n this.#gitOptions = {\n baseDir: options.repositoryRoot,\n maxConcurrentProcesses: options.maxConcurrentProcesses,\n config: [\n `user.name=${options.commitIdentity.name}`,\n `user.email=${options.commitIdentity.email}`,\n ],\n };\n this.#git = simpleGit(options.repositoryRoot, {\n ...this.#gitOptions,\n timeout: { block: options.timeoutMs },\n });\n }\n\n async #execute<Value>(operation: string, action: () => Promise<Value>) {\n try {\n return await action();\n } catch (error) {\n throw normalizeError(operation, error);\n }\n }\n\n async currentBranch() {\n const result = await this.#execute(\"current-branch\", () =>\n this.#git.revparse([\"--abbrev-ref\", \"HEAD\"]),\n );\n if (!isNonEmptyString(result) || result.trim().length === 0) {\n throw new GitRepositoryError(\"malformed-output\", \"current-branch\");\n }\n return result.trim();\n }\n\n async status(pathspecs?: readonly string[]) {\n const validatedPathspecs =\n pathspecs === undefined ? undefined : assertValidPathspecs(pathspecs);\n const result = await this.#execute(\"status\", () =>\n validatedPathspecs === undefined\n ? this.#git.status()\n : this.#git.status([\"--\", ...validatedPathspecs]),\n );\n\n if (\n !isRecord(result) ||\n !Array.isArray(result.files) ||\n (typeof result.current !== \"string\" && result.current !== null) ||\n typeof result.isClean !== \"function\"\n ) {\n throw new GitRepositoryError(\"malformed-output\", \"status\");\n }\n\n const files: GitStatusFile[] = [];\n for (const file of result.files) {\n if (!isRecord(file)) {\n throw new GitRepositoryError(\"malformed-output\", \"status\");\n }\n if (\n typeof file.path !== \"string\" ||\n typeof file.index !== \"string\" ||\n typeof file.working_dir !== \"string\"\n ) {\n throw new GitRepositoryError(\"malformed-output\", \"status\");\n }\n\n files.push({\n path: file.path,\n index: file.index,\n workingDirectory: file.working_dir,\n ...(typeof file.from === \"string\" ? { from: file.from } : {}),\n });\n }\n\n let clean: boolean;\n try {\n clean = result.isClean();\n } catch {\n throw new GitRepositoryError(\"malformed-output\", \"status\");\n }\n if (typeof clean !== \"boolean\") {\n throw new GitRepositoryError(\"malformed-output\", \"status\");\n }\n\n return {\n current: result.current,\n files,\n clean,\n } satisfies GitStatusSnapshot;\n }\n\n async remotes() {\n const result = await this.#execute(\"remotes\", () =>\n this.#git.getRemotes(true),\n );\n if (!Array.isArray(result)) {\n throw new GitRepositoryError(\"malformed-output\", \"remotes\");\n }\n\n const remotes: GitRemoteSnapshot[] = [];\n for (const remote of result) {\n if (!isRecord(remote) || typeof remote.name !== \"string\") {\n throw new GitRepositoryError(\"malformed-output\", \"remotes\");\n }\n const refs = remote.refs;\n if (!isRecord(refs)) {\n throw new GitRepositoryError(\"malformed-output\", \"remotes\");\n }\n if (typeof refs.fetch !== \"string\" || typeof refs.push !== \"string\") {\n throw new GitRepositoryError(\"malformed-output\", \"remotes\");\n }\n\n remotes.push({\n name: remote.name,\n fetchUrl: refs.fetch,\n pushUrl: refs.push,\n });\n }\n return remotes;\n }\n\n async branches() {\n const result = await this.#execute(\"branches\", () =>\n this.#git.branch([\"-a\"]),\n );\n if (\n !isRecord(result) ||\n !Array.isArray(result.all) ||\n (typeof result.current !== \"string\" && result.current !== null) ||\n !result.all.every((branch) => typeof branch === \"string\")\n ) {\n throw new GitRepositoryError(\"malformed-output\", \"branches\");\n }\n\n return {\n current: result.current,\n all: [...result.all],\n } satisfies GitBranchSnapshot;\n }\n\n async fetch(remote: string, branch?: string) {\n assertValidBranchName(remote, \"remote\");\n if (branch !== undefined) assertValidBranchName(branch, \"branch\");\n await this.#execute(\"fetch\", () =>\n branch === undefined\n ? this.#git.fetch(remote)\n : this.#git.fetch(remote, branch),\n );\n }\n\n async checkout(args: readonly string[]) {\n const validatedArgs = assertValidArguments(args, \"checkout\");\n await this.#execute(\"checkout\", () => this.#git.checkout(validatedArgs));\n }\n\n async checkoutLocalBranch(branch: string) {\n assertValidBranchName(branch, \"branch\");\n await this.#execute(\"checkout-local-branch\", () =>\n this.#git.checkoutLocalBranch(branch),\n );\n }\n\n async merge(args: readonly string[]) {\n const validatedArgs = assertValidArguments(args, \"merge\");\n await this.#execute(\"merge\", () => this.#git.merge(validatedArgs));\n }\n\n async add(pathspecs: readonly string[]) {\n const validatedPathspecs = assertValidPathspecs(pathspecs);\n await this.#execute(\"add\", () => this.#git.add(validatedPathspecs));\n }\n\n async commit(message: string, pathspecs?: readonly string[]) {\n if (!isNonEmptyString(message)) {\n throw new GitRepositoryError(\"invalid-configuration\", \"commit-message\");\n }\n const validatedPathspecs =\n pathspecs === undefined ? undefined : assertValidPathspecs(pathspecs);\n\n let result: unknown;\n try {\n result =\n validatedPathspecs === undefined\n ? await this.#git.commit(message)\n : await this.#git.commit(message, [...validatedPathspecs]);\n } catch (error) {\n if (isNothingToCommit(error)) return null;\n throw normalizeError(\"commit\", error);\n }\n if (\n !isRecord(result) ||\n typeof result.branch !== \"string\" ||\n typeof result.commit !== \"string\" ||\n typeof result.root !== \"boolean\"\n ) {\n throw new GitRepositoryError(\"malformed-output\", \"commit\");\n }\n\n return {\n branch: result.branch,\n commit: result.commit,\n root: result.root,\n } satisfies GitCommitSnapshot;\n }\n\n async push(remote: string, branch: string, options: readonly string[] = []) {\n assertValidBranchName(remote, \"remote\");\n assertValidBranchName(branch, \"branch\");\n const validatedOptions = assertValidArguments(options, \"push\");\n await this.#execute(\"push\", () =>\n this.#git.push(remote, branch, validatedOptions),\n );\n }\n\n async pushUpload(\n remote: string,\n branch: string,\n options: readonly string[] = [],\n onProgress?: (progress: GitUploadProgress) => void,\n ) {\n assertValidBranchName(remote, \"remote\");\n assertValidBranchName(branch, \"branch\");\n const validatedOptions = assertValidArguments(options, \"push\");\n const abort = new AbortController();\n const git = simpleGit(this.#gitOptions.baseDir, {\n ...this.#gitOptions,\n abort: abort.signal,\n progress:\n onProgress === undefined\n ? undefined\n : (progress) =>\n onProgress({\n stage: progress.stage,\n progress: progress.progress,\n processed: progress.processed,\n total: progress.total,\n }),\n timeout: { block: UPLOAD_INACTIVITY_TIMEOUT_MS },\n });\n let wallTimer: ReturnType<typeof setTimeout> | undefined;\n const push = git.push(remote, branch, validatedOptions);\n try {\n await Promise.race([\n push,\n new Promise<never>((_, reject) => {\n wallTimer = setTimeout(() => {\n abort.abort();\n reject(new GitRepositoryError(\"timeout\", \"upload\"));\n }, UPLOAD_WALL_TIMEOUT_MS);\n }),\n ]);\n } catch (error) {\n throw normalizeError(\"upload\", error);\n } finally {\n if (wallTimer !== undefined) clearTimeout(wallTimer);\n }\n }\n\n async restore(pathspecs: readonly string[]) {\n const validatedPathspecs = assertValidPathspecs(pathspecs);\n await this.#execute(\"restore\", () =>\n this.#git.checkout([\"--\", ...validatedPathspecs]),\n );\n }\n\n async clean(mode: string, pathspecs: readonly string[]) {\n if (!/^[a-z]+$/u.test(mode)) {\n throw new GitRepositoryError(\"invalid-configuration\", \"clean-mode\");\n }\n const validatedPathspecs = assertValidPathspecs(pathspecs);\n await this.#execute(\"clean\", () =>\n this.#git.clean(mode, validatedPathspecs),\n );\n }\n\n async raw(args: readonly string[]) {\n const validatedArgs = assertValidArguments(args, \"raw\");\n const result = await this.#execute(\"raw\", () =>\n this.#git.raw(validatedArgs),\n );\n if (typeof result !== \"string\") {\n throw new GitRepositoryError(\"malformed-output\", \"raw\");\n }\n return result;\n }\n\n async rawWithEnv(\n args: readonly string[],\n environment: Readonly<Record<string, string>>,\n ) {\n const validatedArgs = assertValidArguments(args, \"raw\");\n if (\n Object.keys(environment).some(\n (key) =>\n !/^[A-Z_][A-Z0-9_]*$/u.test(key) || environment[key] === undefined,\n )\n ) {\n throw new GitRepositoryError(\"invalid-configuration\", \"raw-environment\");\n }\n const git = simpleGit(this.#gitOptions.baseDir, {\n ...this.#gitOptions,\n timeout: { block: DEFAULT_TIMEOUT_MS },\n }).env(environment);\n const result = await this.#execute(\"raw\", () => git.raw(validatedArgs));\n if (typeof result !== \"string\") {\n throw new GitRepositoryError(\"malformed-output\", \"raw\");\n }\n return result;\n }\n}\n\nexport type PrepareIdentityBranchOptions = {\n identityBranch: string;\n primaryBranch: string;\n remote: string;\n};\n\nexport async function prepareIdentityBranch(\n repository: GitRepository,\n options: PrepareIdentityBranchOptions,\n): Promise<void> {\n assertValidBranchName(options.identityBranch, \"identity-branch\");\n assertValidBranchName(options.primaryBranch, \"primary-branch\");\n assertValidBranchName(options.remote, \"remote\");\n\n const currentBranch = await repository.currentBranch();\n if (currentBranch === options.identityBranch) return;\n\n const status = await repository.status();\n if (!status.clean) {\n throw new GitRepositoryError(\"conflict\", \"prepare-identity-branch\");\n }\n\n const remotes = await repository.remotes();\n const configuredRemote = remotes.some(\n (remote) => remote.name === options.remote,\n );\n if (configuredRemote) {\n await repository.fetch(options.remote, options.primaryBranch);\n }\n\n const branches = await repository.branches();\n const hasLocalPrimary = branches.all.includes(options.primaryBranch);\n const remotePrimary = `remotes/${options.remote}/${options.primaryBranch}`;\n const hasRemotePrimary =\n configuredRemote && branches.all.includes(remotePrimary);\n if (!hasLocalPrimary && !hasRemotePrimary) {\n throw new GitRepositoryError(\"command-failure\", \"primary-branch\");\n }\n\n if (hasLocalPrimary) {\n await repository.checkout([options.primaryBranch]);\n } else {\n await repository.checkout([\n \"-b\",\n options.primaryBranch,\n \"--track\",\n `${options.remote}/${options.primaryBranch}`,\n ]);\n }\n if (configuredRemote) {\n await repository.merge([\n `${options.remote}/${options.primaryBranch}`,\n \"--ff-only\",\n ]);\n }\n\n if (branches.all.includes(options.identityBranch)) {\n await repository.checkout([options.identityBranch]);\n return;\n }\n\n const remoteBranch = `remotes/${options.remote}/${options.identityBranch}`;\n if (branches.all.includes(remoteBranch)) {\n await repository.checkout([\n \"-b\",\n options.identityBranch,\n \"--track\",\n `${options.remote}/${options.identityBranch}`,\n ]);\n return;\n }\n\n await repository.checkoutLocalBranch(options.identityBranch);\n}\n\nexport async function commitPath(\n repository: GitRepository,\n pathspec: string,\n message: string,\n): Promise<GitCommitResult> {\n const validatedPathspecs = assertValidPathspecs([pathspec]);\n await repository.add(validatedPathspecs);\n return repository.commit(message, validatedPathspecs);\n}\n\nexport async function discardPath(\n repository: GitRepository,\n pathspec: string,\n): Promise<void> {\n const validatedPathspec = assertValidPathspecs([pathspec])[0]!;\n await repository.raw([\"reset\", \"HEAD\", \"--\", validatedPathspec]);\n await repository.restore([validatedPathspec]);\n await repository.clean(\"fd\", [validatedPathspec]);\n}\n\nexport async function restorePathFromRef(\n repository: GitRepository,\n ref: string,\n pathspec: string,\n): Promise<void> {\n assertValidArguments([ref], \"restore-ref\");\n const validatedPathspec = assertValidPathspecs([pathspec])[0]!;\n await repository.raw([\n \"restore\",\n \"--source\",\n ref,\n \"--staged\",\n \"--worktree\",\n \"--\",\n validatedPathspec,\n ]);\n}\n\nexport async function remoteBranchCommit(\n repository: GitRepository,\n remote: string,\n branch: string,\n) {\n const output = await repository.raw([\n \"ls-remote\",\n remote,\n `refs/heads/${branch}`,\n ]);\n const value = output.trim().split(/\\s+/u)[0];\n return value !== undefined && /^[0-9a-f]{40,64}$/iu.test(value)\n ? value.toLowerCase()\n : null;\n}\n\nexport async function pushCommitToBranch(\n repository: GitRepository,\n remote: string,\n commit: string,\n branch: string,\n upload = false,\n): Promise<GitPushResult> {\n assertValidBranchName(remote, \"remote\");\n assertValidBranchName(branch, \"branch\");\n if (!/^[0-9a-f]{40,64}$/iu.test(commit)) {\n throw new GitRepositoryError(\"invalid-configuration\", \"commit\");\n }\n\n const hasRemote = (await repository.remotes()).some(\n (configuredRemote) => configuredRemote.name === remote,\n );\n if (!hasRemote) return { remoteStatus: \"local-only\" };\n\n try {\n const canUseUploadPolicy = upload && repository.pushUpload !== undefined;\n if (canUseUploadPolicy) {\n await repository.pushUpload!(remote, `${commit}:refs/heads/${branch}`);\n } else {\n await repository.raw([\"push\", remote, `${commit}:refs/heads/${branch}`]);\n }\n } catch (error) {\n try {\n if (\n (await remoteBranchCommit(repository, remote, branch)) ===\n commit.toLowerCase()\n ) {\n return { remoteStatus: \"pushed\" };\n }\n } catch {\n // Preserve the original push classification when confirmation is also\n // unavailable. The caller can surface this as upload-unconfirmed.\n }\n throw error;\n }\n\n if (\n (await remoteBranchCommit(repository, remote, branch)) !==\n commit.toLowerCase()\n ) {\n throw new GitRepositoryError(\"conflict\", \"source-confirmation\");\n }\n return { remoteStatus: \"pushed\" };\n}\n\nexport async function pushBranch(\n repository: GitRepository,\n remote: string,\n branch: string,\n): Promise<GitPushResult> {\n assertValidBranchName(remote, \"remote\");\n assertValidBranchName(branch, \"branch\");\n\n const hasRemote = (await repository.remotes()).some(\n (configuredRemote) => configuredRemote.name === remote,\n );\n if (!hasRemote) return { remoteStatus: \"local-only\" };\n\n await repository.push(remote, branch, [\"--set-upstream\"]);\n return { remoteStatus: \"pushed\" };\n}\n\nexport function createGitRepository(\n options: GitRepositoryOptions,\n): GitRepository {\n if (!isAbsolute(options.repositoryRoot)) {\n throw new GitRepositoryError(\"invalid-configuration\", \"repository-root\");\n }\n\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const maxConcurrentProcesses =\n options.maxConcurrentProcesses ?? DEFAULT_MAX_CONCURRENT_PROCESSES;\n const commitIdentity = options.commitIdentity ?? DEFAULT_COMMIT_IDENTITY;\n\n assertValidPositiveInteger(timeoutMs, \"timeout\");\n assertValidPositiveInteger(\n maxConcurrentProcesses,\n \"max-concurrent-processes\",\n );\n\n return new SimpleGitRepository({\n repositoryRoot: options.repositoryRoot,\n timeoutMs,\n maxConcurrentProcesses,\n commitIdentity,\n });\n}\n"]}
|
package/dist/github-cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github-cli.d.ts","sourceRoot":"","sources":["../src/github-cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAGL,KAAK,sBAAsB,EAC5B,MAAM,qBAAqB,CAAC;AAsB7B,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,iBAAiB,GAAG,SAAS,CAAC;AAE7E,qBAAa,cAAe,SAAQ,KAAK;IACvC,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAC;IAEtC,YAAY,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE,oBAAgC,EAIpE;CACF;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,sBAAsB,CAAC;CAClC,CAAC;AAEF,MAAM,WAAW,mBAAmB;IAClC,OAAO,IAAI,OAAO,CAAC,eAAe,CAAC,CAAC;IACpC,aAAa,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAAC;CAC7C;
|
|
1
|
+
{"version":3,"file":"github-cli.d.ts","sourceRoot":"","sources":["../src/github-cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAGL,KAAK,sBAAsB,EAC5B,MAAM,qBAAqB,CAAC;AAsB7B,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,iBAAiB,GAAG,SAAS,CAAC;AAE7E,qBAAa,cAAe,SAAQ,KAAK;IACvC,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAC;IAEtC,YAAY,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE,oBAAgC,EAIpE;CACF;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,sBAAsB,CAAC;CAClC,CAAC;AAEF,MAAM,WAAW,mBAAmB;IAClC,OAAO,IAAI,OAAO,CAAC,eAAe,CAAC,CAAC;IACpC,aAAa,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAAC;CAC7C;AA0GD,qBAAa,eAAgB,YAAW,mBAAmB;;IACzD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAI1B,YAAY,OAAO,EAAE,sBAAsB,EAG1C;IAEK,OAAO,IAAI,OAAO,CAAC,eAAe,CAAC,CA+BxC;IAEK,aAAa,+BA6GlB;CACF","sourcesContent":["import {\n parseBonfireIdentity,\n type BonfireIdentity,\n} from \"@ebay-dt/bonfire-core\";\nimport {\n defaultGitHubCliProcessRunner,\n type GitHubCliChildProcess,\n type GitHubCliProcessRunner,\n} from \"./process-runner.js\";\n\nconst GH_EXECUTABLE = \"gh\";\nconst IDENTITY_TIMEOUT = 10_000;\nconst IDENTITY_MAX_BUFFER = 1024 * 1024;\nconst DEVICE_LOGIN_TIMEOUT = 10_000;\nconst ACTIVE_LOGIN_WINDOW = 10 * 60 * 1000;\nconst GH_LOGIN_CODE_LABEL_PATTERN = /\\bone[-\\s]time\\s+code\\b/i;\nconst GH_DEVICE_CODE_PATTERN = /\\b[A-Za-z0-9]+(?:-[A-Za-z0-9]+)+\\b/;\nconst ANSI_ESCAPE_PATTERN = new RegExp(\n `${String.fromCharCode(27)}\\\\[[0-?]*[ -/]*[@-~]`,\n \"g\",\n);\n\ntype GitHubCliFailure = {\n code?: unknown;\n killed?: unknown;\n signal?: unknown;\n stderr?: unknown;\n stdout?: unknown;\n};\n\nexport type GitHubCliErrorReason = \"missing\" | \"unauthenticated\" | \"unknown\";\n\nexport class GitHubCliError extends Error {\n readonly reason: GitHubCliErrorReason;\n\n constructor(message: string, reason: GitHubCliErrorReason = \"unknown\") {\n super(message);\n this.name = \"GitHubCliError\";\n this.reason = reason;\n }\n}\n\nexport type GitHubCliWebLogin = {\n code: string | null;\n deviceUrl: string;\n};\n\nexport type GitHubCliClientOptions = {\n hostname: string;\n process?: GitHubCliProcessRunner;\n};\n\nexport interface GitHubCliClientLike {\n getUser(): Promise<BonfireIdentity>;\n startWebLogin(): Promise<GitHubCliWebLogin>;\n}\n\ntype ActiveLogin = {\n child: GitHubCliChildProcess;\n code: string | null;\n settled: boolean;\n startedAt: number;\n promise: Promise<GitHubCliWebLogin>;\n};\n\nfunction asFailure(error: unknown): GitHubCliFailure {\n return error && typeof error === \"object\" ? (error as GitHubCliFailure) : {};\n}\n\nfunction outputFrom(value: unknown): string {\n return typeof value === \"string\" ? value : \"\";\n}\n\nfunction extractDeviceCode(output: string): string | null {\n const cleanOutput = output\n .replace(ANSI_ESCAPE_PATTERN, \"\")\n .replace(/\\r/g, \"\");\n const lines = cleanOutput.split(\"\\n\");\n\n for (let index = 0; index < lines.length; index += 1) {\n const line = lines[index];\n if (line === undefined) continue;\n const label = line.match(GH_LOGIN_CODE_LABEL_PATTERN);\n if (!label || label.index === undefined) continue;\n\n const remainder = line.slice(label.index + label[0].length);\n const match =\n remainder.match(GH_DEVICE_CODE_PATTERN) ??\n lines[index + 1]?.match(GH_DEVICE_CODE_PATTERN);\n if (match) return match[0];\n }\n\n return null;\n}\n\nfunction projectIdentityFields(value: unknown) {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return value;\n }\n\n const record = value as Record<string, unknown>;\n return {\n login: record.login,\n ...(Object.hasOwn(record, \"name\") ? { name: record.name } : {}),\n avatar_url: record.avatar_url,\n };\n}\n\nfunction isUnauthenticatedOutput(output: string): boolean {\n const normalized = output.toLowerCase();\n return (\n normalized.includes(\"gh auth login\") ||\n normalized.includes(\"not logged into\") ||\n normalized.includes(\"authentication required\") ||\n normalized.includes(\"must authenticate\") ||\n /\\b(?:http(?:\\s+status)?\\s*)?401\\b/.test(normalized)\n );\n}\n\nfunction describeFailure(failure: GitHubCliFailure): string {\n if (failure.code === \"ENOENT\") {\n return \"GitHub CLI (`gh`) is not installed or is not available on PATH.\";\n }\n\n if (\n failure.code === \"ETIMEDOUT\" ||\n failure.killed === true ||\n failure.signal === \"SIGTERM\"\n ) {\n return \"GitHub CLI command timed out.\";\n }\n\n if (failure.code === \"ERR_CHILD_PROCESS_STDIO_MAXBUFFER\") {\n return \"GitHub CLI output exceeded the allowed limit.\";\n }\n\n return \"GitHub CLI command failed.\";\n}\n\nfunction commandFailure(error: unknown, hostname: string): GitHubCliError {\n const failure = asFailure(error);\n const output = `${outputFrom(failure.stdout)}\\n${outputFrom(failure.stderr)}`;\n const guidance = ` Run: gh auth login --hostname ${hostname}`;\n\n if (failure.code === \"ENOENT\") {\n return new GitHubCliError(\n `GitHub CLI (\\`gh\\`) is not installed or is not available on PATH.${guidance}`,\n \"missing\",\n );\n }\n\n if (isUnauthenticatedOutput(output)) {\n return new GitHubCliError(\n `GitHub CLI is not authenticated for ${hostname}.${guidance}`,\n \"unauthenticated\",\n );\n }\n\n return new GitHubCliError(`${describeFailure(failure)}${guidance}`);\n}\n\nexport class GitHubCliClient implements GitHubCliClientLike {\n readonly hostname: string;\n readonly #process: GitHubCliProcessRunner;\n #activeLogin: ActiveLogin | null = null;\n\n constructor(options: GitHubCliClientOptions) {\n this.hostname = options.hostname;\n this.#process = options.process ?? defaultGitHubCliProcessRunner;\n }\n\n async getUser(): Promise<BonfireIdentity> {\n const args = [\"api\", \"--hostname\", this.hostname, \"user\"];\n let result;\n\n try {\n result = await this.#process.execFile(GH_EXECUTABLE, args, {\n timeout: IDENTITY_TIMEOUT,\n maxBuffer: IDENTITY_MAX_BUFFER,\n });\n } catch (error) {\n throw commandFailure(error, this.hostname);\n }\n\n if (isUnauthenticatedOutput(`${result.stdout}\\n${result.stderr}`)) {\n throw commandFailure(result, this.hostname);\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(result.stdout);\n } catch {\n throw new GitHubCliError(\n `GitHub CLI returned malformed user data. Run: gh auth login --hostname ${this.hostname}`,\n );\n }\n\n try {\n return parseBonfireIdentity(projectIdentityFields(parsed));\n } catch {\n throw new GitHubCliError(\"GitHub CLI returned an invalid user profile.\");\n }\n }\n\n async startWebLogin() {\n const activeLogin = this.#activeLogin;\n if (activeLogin) {\n const withinReuseWindow =\n Date.now() - activeLogin.startedAt < ACTIVE_LOGIN_WINDOW;\n if (\n !activeLogin.settled ||\n (activeLogin.code !== null && withinReuseWindow)\n ) {\n return activeLogin.promise;\n }\n\n try {\n activeLogin.child.kill(\"SIGTERM\");\n } catch {\n throw new GitHubCliError(\n \"The previous GitHub CLI login could not be terminated.\",\n );\n }\n this.#activeLogin = null;\n }\n\n const spawn = this.#process.spawn;\n if (!spawn) {\n throw new GitHubCliError(\"GitHub CLI device login is unavailable.\");\n }\n\n let child: GitHubCliChildProcess;\n try {\n child = spawn(\n GH_EXECUTABLE,\n [\n \"auth\",\n \"login\",\n \"--hostname\",\n this.hostname,\n \"--web\",\n \"--clipboard\",\n \"--git-protocol\",\n \"ssh\",\n \"--skip-ssh-key\",\n ],\n { stdio: [\"ignore\", \"pipe\", \"pipe\"] },\n );\n } catch (error) {\n throw commandFailure(error, this.hostname);\n }\n\n let resolveLogin!: (login: GitHubCliWebLogin) => void;\n let rejectLogin!: (error: GitHubCliError) => void;\n const promise = new Promise<GitHubCliWebLogin>((resolve, reject) => {\n resolveLogin = resolve;\n rejectLogin = reject;\n });\n const login: ActiveLogin = {\n child,\n code: null,\n settled: false,\n startedAt: Date.now(),\n promise,\n };\n this.#activeLogin = login;\n\n let output = \"\";\n let settled = false;\n let timer: ReturnType<typeof setTimeout>;\n\n const clearActiveLogin = () => {\n if (this.#activeLogin?.child === child) this.#activeLogin = null;\n };\n\n const settle = (code: string | null) => {\n if (settled) return;\n settled = true;\n login.code = code;\n login.settled = true;\n clearTimeout(timer);\n resolveLogin({\n code,\n deviceUrl: `https://${this.hostname}/login/device`,\n });\n };\n\n const fail = (error: unknown) => {\n clearActiveLogin();\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n rejectLogin(commandFailure(error, this.hostname));\n };\n\n const inspectOutput = (chunk: string | Uint8Array) => {\n output +=\n typeof chunk === \"string\" ? chunk : Buffer.from(chunk).toString(\"utf8\");\n const code = extractDeviceCode(output);\n if (code) settle(code);\n };\n\n timer = setTimeout(() => settle(null), DEVICE_LOGIN_TIMEOUT);\n timer.unref?.();\n child.stdout?.on(\"data\", inspectOutput);\n child.stderr?.on(\"data\", inspectOutput);\n child.once(\"error\", fail);\n child.once(\"close\", () => {\n if (!settled) settle(null);\n clearActiveLogin();\n });\n\n return promise;\n }\n}\n"]}
|
package/dist/github-cli.js
CHANGED
|
@@ -23,7 +23,9 @@ function outputFrom(value) {
|
|
|
23
23
|
return typeof value === "string" ? value : "";
|
|
24
24
|
}
|
|
25
25
|
function extractDeviceCode(output) {
|
|
26
|
-
const cleanOutput = output
|
|
26
|
+
const cleanOutput = output
|
|
27
|
+
.replace(ANSI_ESCAPE_PATTERN, "")
|
|
28
|
+
.replace(/\r/g, "");
|
|
27
29
|
const lines = cleanOutput.split("\n");
|
|
28
30
|
for (let index = 0; index < lines.length; index += 1) {
|
|
29
31
|
const line = lines[index];
|
package/dist/github-cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github-cli.js","sourceRoot":"","sources":["../src/github-cli.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n parseBonfireIdentity,\n type BonfireIdentity,\n} from \"@ebay-dt/bonfire-core\";\nimport {\n defaultGitHubCliProcessRunner,\n type GitHubCliChildProcess,\n type GitHubCliProcessRunner,\n} from \"./process-runner.js\";\n\nconst GH_EXECUTABLE = \"gh\";\nconst IDENTITY_TIMEOUT = 10_000;\nconst IDENTITY_MAX_BUFFER = 1024 * 1024;\nconst DEVICE_LOGIN_TIMEOUT = 10_000;\nconst ACTIVE_LOGIN_WINDOW = 10 * 60 * 1000;\nconst GH_LOGIN_CODE_LABEL_PATTERN = /\\bone[-\\s]time\\s+code\\b/i;\nconst GH_DEVICE_CODE_PATTERN = /\\b[A-Za-z0-9]+(?:-[A-Za-z0-9]+)+\\b/;\nconst ANSI_ESCAPE_PATTERN = new RegExp(\n `${String.fromCharCode(27)}\\\\[[0-?]*[ -/]*[@-~]`,\n \"g\",\n);\n\ntype GitHubCliFailure = {\n code?: unknown;\n killed?: unknown;\n signal?: unknown;\n stderr?: unknown;\n stdout?: unknown;\n};\n\nexport type GitHubCliErrorReason = \"missing\" | \"unauthenticated\" | \"unknown\";\n\nexport class GitHubCliError extends Error {\n readonly reason: GitHubCliErrorReason;\n\n constructor(message: string, reason: GitHubCliErrorReason = \"unknown\") {\n super(message);\n this.name = \"GitHubCliError\";\n this.reason = reason;\n }\n}\n\nexport type GitHubCliWebLogin = {\n code: string | null;\n deviceUrl: string;\n};\n\nexport type GitHubCliClientOptions = {\n hostname: string;\n process?: GitHubCliProcessRunner;\n};\n\nexport interface GitHubCliClientLike {\n getUser(): Promise<BonfireIdentity>;\n startWebLogin(): Promise<GitHubCliWebLogin>;\n}\n\ntype ActiveLogin = {\n child: GitHubCliChildProcess;\n code: string | null;\n settled: boolean;\n startedAt: number;\n promise: Promise<GitHubCliWebLogin>;\n};\n\nfunction asFailure(error: unknown): GitHubCliFailure {\n return error && typeof error === \"object\" ? (error as GitHubCliFailure) : {};\n}\n\nfunction outputFrom(value: unknown): string {\n return typeof value === \"string\" ? value : \"\";\n}\n\nfunction extractDeviceCode(output: string): string | null {\n const cleanOutput = output.replace(ANSI_ESCAPE_PATTERN, \"\").replace(/\\r/g, \"\");\n const lines = cleanOutput.split(\"\\n\");\n\n for (let index = 0; index < lines.length; index += 1) {\n const line = lines[index];\n if (line === undefined) continue;\n const label = line.match(GH_LOGIN_CODE_LABEL_PATTERN);\n if (!label || label.index === undefined) continue;\n\n const remainder = line.slice(label.index + label[0].length);\n const match =\n remainder.match(GH_DEVICE_CODE_PATTERN) ??\n lines[index + 1]?.match(GH_DEVICE_CODE_PATTERN);\n if (match) return match[0];\n }\n\n return null;\n}\n\nfunction projectIdentityFields(value: unknown) {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return value;\n }\n\n const record = value as Record<string, unknown>;\n return {\n login: record.login,\n ...(Object.hasOwn(record, \"name\") ? { name: record.name } : {}),\n avatar_url: record.avatar_url,\n };\n}\n\nfunction isUnauthenticatedOutput(output: string): boolean {\n const normalized = output.toLowerCase();\n return (\n normalized.includes(\"gh auth login\") ||\n normalized.includes(\"not logged into\") ||\n normalized.includes(\"authentication required\") ||\n normalized.includes(\"must authenticate\") ||\n /\\b(?:http(?:\\s+status)?\\s*)?401\\b/.test(normalized)\n );\n}\n\nfunction describeFailure(failure: GitHubCliFailure): string {\n if (failure.code === \"ENOENT\") {\n return \"GitHub CLI (`gh`) is not installed or is not available on PATH.\";\n }\n\n if (\n failure.code === \"ETIMEDOUT\" ||\n failure.killed === true ||\n failure.signal === \"SIGTERM\"\n ) {\n return \"GitHub CLI command timed out.\";\n }\n\n if (failure.code === \"ERR_CHILD_PROCESS_STDIO_MAXBUFFER\") {\n return \"GitHub CLI output exceeded the allowed limit.\";\n }\n\n return \"GitHub CLI command failed.\";\n}\n\nfunction commandFailure(error: unknown, hostname: string): GitHubCliError {\n const failure = asFailure(error);\n const output = `${outputFrom(failure.stdout)}\\n${outputFrom(failure.stderr)}`;\n const guidance = ` Run: gh auth login --hostname ${hostname}`;\n\n if (failure.code === \"ENOENT\") {\n return new GitHubCliError(\n `GitHub CLI (\\`gh\\`) is not installed or is not available on PATH.${guidance}`,\n \"missing\",\n );\n }\n\n if (isUnauthenticatedOutput(output)) {\n return new GitHubCliError(\n `GitHub CLI is not authenticated for ${hostname}.${guidance}`,\n \"unauthenticated\",\n );\n }\n\n return new GitHubCliError(`${describeFailure(failure)}${guidance}`);\n}\n\nexport class GitHubCliClient implements GitHubCliClientLike {\n readonly hostname: string;\n readonly #process: GitHubCliProcessRunner;\n #activeLogin: ActiveLogin | null = null;\n\n constructor(options: GitHubCliClientOptions) {\n this.hostname = options.hostname;\n this.#process = options.process ?? defaultGitHubCliProcessRunner;\n }\n\n async getUser(): Promise<BonfireIdentity> {\n const args = [\"api\", \"--hostname\", this.hostname, \"user\"];\n let result;\n\n try {\n result = await this.#process.execFile(GH_EXECUTABLE, args, {\n timeout: IDENTITY_TIMEOUT,\n maxBuffer: IDENTITY_MAX_BUFFER,\n });\n } catch (error) {\n throw commandFailure(error, this.hostname);\n }\n\n if (isUnauthenticatedOutput(`${result.stdout}\\n${result.stderr}`)) {\n throw commandFailure(result, this.hostname);\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(result.stdout);\n } catch {\n throw new GitHubCliError(\n `GitHub CLI returned malformed user data. Run: gh auth login --hostname ${this.hostname}`,\n );\n }\n\n try {\n return parseBonfireIdentity(projectIdentityFields(parsed));\n } catch {\n throw new GitHubCliError(\"GitHub CLI returned an invalid user profile.\");\n }\n }\n\n async startWebLogin() {\n const activeLogin = this.#activeLogin;\n if (activeLogin) {\n const withinReuseWindow =\n Date.now() - activeLogin.startedAt < ACTIVE_LOGIN_WINDOW;\n if (\n !activeLogin.settled ||\n (activeLogin.code !== null && withinReuseWindow)\n ) {\n return activeLogin.promise;\n }\n\n try {\n activeLogin.child.kill(\"SIGTERM\");\n } catch {\n throw new GitHubCliError(\n \"The previous GitHub CLI login could not be terminated.\",\n );\n }\n this.#activeLogin = null;\n }\n\n const spawn = this.#process.spawn;\n if (!spawn) {\n throw new GitHubCliError(\"GitHub CLI device login is unavailable.\");\n }\n\n let child: GitHubCliChildProcess;\n try {\n child = spawn(\n GH_EXECUTABLE,\n [\n \"auth\",\n \"login\",\n \"--hostname\",\n this.hostname,\n \"--web\",\n \"--clipboard\",\n \"--git-protocol\",\n \"ssh\",\n \"--skip-ssh-key\",\n ],\n { stdio: [\"ignore\", \"pipe\", \"pipe\"] },\n );\n } catch (error) {\n throw commandFailure(error, this.hostname);\n }\n\n let resolveLogin!: (login: GitHubCliWebLogin) => void;\n let rejectLogin!: (error: GitHubCliError) => void;\n const promise = new Promise<GitHubCliWebLogin>((resolve, reject) => {\n resolveLogin = resolve;\n rejectLogin = reject;\n });\n const login: ActiveLogin = {\n child,\n code: null,\n settled: false,\n startedAt: Date.now(),\n promise,\n };\n this.#activeLogin = login;\n\n let output = \"\";\n let settled = false;\n let timer: ReturnType<typeof setTimeout>;\n\n const clearActiveLogin = () => {\n if (this.#activeLogin?.child === child) this.#activeLogin = null;\n };\n\n const settle = (code: string | null) => {\n if (settled) return;\n settled = true;\n login.code = code;\n login.settled = true;\n clearTimeout(timer);\n resolveLogin({\n code,\n deviceUrl: `https://${this.hostname}/login/device`,\n });\n };\n\n const fail = (error: unknown) => {\n clearActiveLogin();\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n rejectLogin(commandFailure(error, this.hostname));\n };\n\n const inspectOutput = (chunk: string | Uint8Array) => {\n output +=\n typeof chunk === \"string\" ? chunk : Buffer.from(chunk).toString(\"utf8\");\n const code = extractDeviceCode(output);\n if (code) settle(code);\n };\n\n timer = setTimeout(() => settle(null), DEVICE_LOGIN_TIMEOUT);\n timer.unref?.();\n child.stdout?.on(\"data\", inspectOutput);\n child.stderr?.on(\"data\", inspectOutput);\n child.once(\"error\", fail);\n child.once(\"close\", () => {\n if (!settled) settle(null);\n clearActiveLogin();\n });\n\n return promise;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"github-cli.js","sourceRoot":"","sources":["../src/github-cli.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n parseBonfireIdentity,\n type BonfireIdentity,\n} from \"@ebay-dt/bonfire-core\";\nimport {\n defaultGitHubCliProcessRunner,\n type GitHubCliChildProcess,\n type GitHubCliProcessRunner,\n} from \"./process-runner.js\";\n\nconst GH_EXECUTABLE = \"gh\";\nconst IDENTITY_TIMEOUT = 10_000;\nconst IDENTITY_MAX_BUFFER = 1024 * 1024;\nconst DEVICE_LOGIN_TIMEOUT = 10_000;\nconst ACTIVE_LOGIN_WINDOW = 10 * 60 * 1000;\nconst GH_LOGIN_CODE_LABEL_PATTERN = /\\bone[-\\s]time\\s+code\\b/i;\nconst GH_DEVICE_CODE_PATTERN = /\\b[A-Za-z0-9]+(?:-[A-Za-z0-9]+)+\\b/;\nconst ANSI_ESCAPE_PATTERN = new RegExp(\n `${String.fromCharCode(27)}\\\\[[0-?]*[ -/]*[@-~]`,\n \"g\",\n);\n\ntype GitHubCliFailure = {\n code?: unknown;\n killed?: unknown;\n signal?: unknown;\n stderr?: unknown;\n stdout?: unknown;\n};\n\nexport type GitHubCliErrorReason = \"missing\" | \"unauthenticated\" | \"unknown\";\n\nexport class GitHubCliError extends Error {\n readonly reason: GitHubCliErrorReason;\n\n constructor(message: string, reason: GitHubCliErrorReason = \"unknown\") {\n super(message);\n this.name = \"GitHubCliError\";\n this.reason = reason;\n }\n}\n\nexport type GitHubCliWebLogin = {\n code: string | null;\n deviceUrl: string;\n};\n\nexport type GitHubCliClientOptions = {\n hostname: string;\n process?: GitHubCliProcessRunner;\n};\n\nexport interface GitHubCliClientLike {\n getUser(): Promise<BonfireIdentity>;\n startWebLogin(): Promise<GitHubCliWebLogin>;\n}\n\ntype ActiveLogin = {\n child: GitHubCliChildProcess;\n code: string | null;\n settled: boolean;\n startedAt: number;\n promise: Promise<GitHubCliWebLogin>;\n};\n\nfunction asFailure(error: unknown): GitHubCliFailure {\n return error && typeof error === \"object\" ? (error as GitHubCliFailure) : {};\n}\n\nfunction outputFrom(value: unknown): string {\n return typeof value === \"string\" ? value : \"\";\n}\n\nfunction extractDeviceCode(output: string): string | null {\n const cleanOutput = output\n .replace(ANSI_ESCAPE_PATTERN, \"\")\n .replace(/\\r/g, \"\");\n const lines = cleanOutput.split(\"\\n\");\n\n for (let index = 0; index < lines.length; index += 1) {\n const line = lines[index];\n if (line === undefined) continue;\n const label = line.match(GH_LOGIN_CODE_LABEL_PATTERN);\n if (!label || label.index === undefined) continue;\n\n const remainder = line.slice(label.index + label[0].length);\n const match =\n remainder.match(GH_DEVICE_CODE_PATTERN) ??\n lines[index + 1]?.match(GH_DEVICE_CODE_PATTERN);\n if (match) return match[0];\n }\n\n return null;\n}\n\nfunction projectIdentityFields(value: unknown) {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return value;\n }\n\n const record = value as Record<string, unknown>;\n return {\n login: record.login,\n ...(Object.hasOwn(record, \"name\") ? { name: record.name } : {}),\n avatar_url: record.avatar_url,\n };\n}\n\nfunction isUnauthenticatedOutput(output: string): boolean {\n const normalized = output.toLowerCase();\n return (\n normalized.includes(\"gh auth login\") ||\n normalized.includes(\"not logged into\") ||\n normalized.includes(\"authentication required\") ||\n normalized.includes(\"must authenticate\") ||\n /\\b(?:http(?:\\s+status)?\\s*)?401\\b/.test(normalized)\n );\n}\n\nfunction describeFailure(failure: GitHubCliFailure): string {\n if (failure.code === \"ENOENT\") {\n return \"GitHub CLI (`gh`) is not installed or is not available on PATH.\";\n }\n\n if (\n failure.code === \"ETIMEDOUT\" ||\n failure.killed === true ||\n failure.signal === \"SIGTERM\"\n ) {\n return \"GitHub CLI command timed out.\";\n }\n\n if (failure.code === \"ERR_CHILD_PROCESS_STDIO_MAXBUFFER\") {\n return \"GitHub CLI output exceeded the allowed limit.\";\n }\n\n return \"GitHub CLI command failed.\";\n}\n\nfunction commandFailure(error: unknown, hostname: string): GitHubCliError {\n const failure = asFailure(error);\n const output = `${outputFrom(failure.stdout)}\\n${outputFrom(failure.stderr)}`;\n const guidance = ` Run: gh auth login --hostname ${hostname}`;\n\n if (failure.code === \"ENOENT\") {\n return new GitHubCliError(\n `GitHub CLI (\\`gh\\`) is not installed or is not available on PATH.${guidance}`,\n \"missing\",\n );\n }\n\n if (isUnauthenticatedOutput(output)) {\n return new GitHubCliError(\n `GitHub CLI is not authenticated for ${hostname}.${guidance}`,\n \"unauthenticated\",\n );\n }\n\n return new GitHubCliError(`${describeFailure(failure)}${guidance}`);\n}\n\nexport class GitHubCliClient implements GitHubCliClientLike {\n readonly hostname: string;\n readonly #process: GitHubCliProcessRunner;\n #activeLogin: ActiveLogin | null = null;\n\n constructor(options: GitHubCliClientOptions) {\n this.hostname = options.hostname;\n this.#process = options.process ?? defaultGitHubCliProcessRunner;\n }\n\n async getUser(): Promise<BonfireIdentity> {\n const args = [\"api\", \"--hostname\", this.hostname, \"user\"];\n let result;\n\n try {\n result = await this.#process.execFile(GH_EXECUTABLE, args, {\n timeout: IDENTITY_TIMEOUT,\n maxBuffer: IDENTITY_MAX_BUFFER,\n });\n } catch (error) {\n throw commandFailure(error, this.hostname);\n }\n\n if (isUnauthenticatedOutput(`${result.stdout}\\n${result.stderr}`)) {\n throw commandFailure(result, this.hostname);\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(result.stdout);\n } catch {\n throw new GitHubCliError(\n `GitHub CLI returned malformed user data. Run: gh auth login --hostname ${this.hostname}`,\n );\n }\n\n try {\n return parseBonfireIdentity(projectIdentityFields(parsed));\n } catch {\n throw new GitHubCliError(\"GitHub CLI returned an invalid user profile.\");\n }\n }\n\n async startWebLogin() {\n const activeLogin = this.#activeLogin;\n if (activeLogin) {\n const withinReuseWindow =\n Date.now() - activeLogin.startedAt < ACTIVE_LOGIN_WINDOW;\n if (\n !activeLogin.settled ||\n (activeLogin.code !== null && withinReuseWindow)\n ) {\n return activeLogin.promise;\n }\n\n try {\n activeLogin.child.kill(\"SIGTERM\");\n } catch {\n throw new GitHubCliError(\n \"The previous GitHub CLI login could not be terminated.\",\n );\n }\n this.#activeLogin = null;\n }\n\n const spawn = this.#process.spawn;\n if (!spawn) {\n throw new GitHubCliError(\"GitHub CLI device login is unavailable.\");\n }\n\n let child: GitHubCliChildProcess;\n try {\n child = spawn(\n GH_EXECUTABLE,\n [\n \"auth\",\n \"login\",\n \"--hostname\",\n this.hostname,\n \"--web\",\n \"--clipboard\",\n \"--git-protocol\",\n \"ssh\",\n \"--skip-ssh-key\",\n ],\n { stdio: [\"ignore\", \"pipe\", \"pipe\"] },\n );\n } catch (error) {\n throw commandFailure(error, this.hostname);\n }\n\n let resolveLogin!: (login: GitHubCliWebLogin) => void;\n let rejectLogin!: (error: GitHubCliError) => void;\n const promise = new Promise<GitHubCliWebLogin>((resolve, reject) => {\n resolveLogin = resolve;\n rejectLogin = reject;\n });\n const login: ActiveLogin = {\n child,\n code: null,\n settled: false,\n startedAt: Date.now(),\n promise,\n };\n this.#activeLogin = login;\n\n let output = \"\";\n let settled = false;\n let timer: ReturnType<typeof setTimeout>;\n\n const clearActiveLogin = () => {\n if (this.#activeLogin?.child === child) this.#activeLogin = null;\n };\n\n const settle = (code: string | null) => {\n if (settled) return;\n settled = true;\n login.code = code;\n login.settled = true;\n clearTimeout(timer);\n resolveLogin({\n code,\n deviceUrl: `https://${this.hostname}/login/device`,\n });\n };\n\n const fail = (error: unknown) => {\n clearActiveLogin();\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n rejectLogin(commandFailure(error, this.hostname));\n };\n\n const inspectOutput = (chunk: string | Uint8Array) => {\n output +=\n typeof chunk === \"string\" ? chunk : Buffer.from(chunk).toString(\"utf8\");\n const code = extractDeviceCode(output);\n if (code) settle(code);\n };\n\n timer = setTimeout(() => settle(null), DEVICE_LOGIN_TIMEOUT);\n timer.unref?.();\n child.stdout?.on(\"data\", inspectOutput);\n child.stderr?.on(\"data\", inspectOutput);\n child.once(\"error\", fail);\n child.once(\"close\", () => {\n if (!settled) settle(null);\n clearActiveLogin();\n });\n\n return promise;\n }\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -12,4 +12,5 @@ export type { PreparePrototypeFiles, PreparePrototypeFilesRequest, } from "./pre
|
|
|
12
12
|
export { LocalPrototypeLifecycle, type LocalPrototypeLifecycleOptions, type PrototypeLifecycle, } from "./lifecycle/local-prototype-lifecycle.js";
|
|
13
13
|
export { assertIdentityBranchReady, hasUnresolvedRepositoryOperation, synchronizeIdentityBranch, type RepositorySynchronizationResult, type SynchronizationDeferredReason, type SynchronizationUnsafeReason, type SynchronizeIdentityBranchOptions, } from "./lifecycle/repository-synchronization.js";
|
|
14
14
|
export { getRepositorySummary, type RepositorySummaryOptions, } from "./lifecycle/repository-summary.js";
|
|
15
|
+
export { clearPreparationMarker, hasPreparationMarker, preparationMarkerPath, readPreparationMarker, writePreparationMarker, type DependencyInstaller, } from "./lifecycle/preparation-marker.js";
|
|
15
16
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,uBAAuB,EACvB,KAAK,+BAA+B,EACpC,KAAK,kBAAkB,EACvB,KAAK,2BAA2B,EAChC,KAAK,wBAAwB,GAC9B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,eAAe,EACf,cAAc,EACd,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,GACvB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,gBAAgB,EAChB,KAAK,oBAAoB,GAC1B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,4BAA4B,EAC5B,KAAK,uBAAuB,EAC5B,KAAK,6BAA6B,GACnC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,qBAAqB,EACrB,KAAK,yBAAyB,EAC9B,KAAK,4BAA4B,GAClC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,kBAAkB,EAClB,0BAA0B,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,EAC9B,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,GAC7B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,cAAc,EACd,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,WAAW,EAChB,KAAK,kBAAkB,GACxB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,sBAAsB,EACtB,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,GAC/B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,oBAAoB,EACpB,yBAAyB,EACzB,KAAK,6BAA6B,EAClC,KAAK,wBAAwB,EAC7B,KAAK,2BAA2B,GACjC,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,qBAAqB,EACrB,4BAA4B,GAC7B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,uBAAuB,EACvB,KAAK,8BAA8B,EACnC,KAAK,kBAAkB,GACxB,MAAM,0CAA0C,CAAC;AAClD,OAAO,EACL,yBAAyB,EACzB,gCAAgC,EAChC,yBAAyB,EACzB,KAAK,+BAA+B,EACpC,KAAK,6BAA6B,EAClC,KAAK,2BAA2B,EAChC,KAAK,gCAAgC,GACtC,MAAM,2CAA2C,CAAC;AACnD,OAAO,EACL,oBAAoB,EACpB,KAAK,wBAAwB,GAC9B,MAAM,mCAAmC,CAAC","sourcesContent":["export {\n createDeploymentProvider,\n DeploymentProviderError,\n type CreateDeploymentProviderOptions,\n type DeploymentProvider,\n type DeploymentProviderErrorKind,\n type DeploymentProviderResult,\n} from \"./deployment-provider.js\";\nexport {\n GitHubCliClient,\n GitHubCliError,\n type GitHubCliClientLike,\n type GitHubCliClientOptions,\n type GitHubCliErrorReason,\n type GitHubCliWebLogin,\n} from \"./github-cli.js\";\nexport type {\n GitHubCliChildProcess,\n GitHubCliExecOptions,\n GitHubCliExecResult,\n GitHubCliOutputStream,\n GitHubCliProcessRunner,\n GitHubCliSpawnOptions,\n} from \"./process-runner.js\";\nexport {\n PrototypeCatalog,\n type PrototypeCatalogLike,\n} from \"./prototype-catalog.js\";\nexport {\n resolvePrototypeCatalogPaths,\n type PrototypeCatalogOptions,\n type ResolvedPrototypeCatalogPaths,\n} from \"./prototype-paths.js\";\nexport {\n PrototypeAgentService,\n type PrototypeAgentServiceLike,\n type PrototypeAgentServiceOptions,\n} from \"./agent-service.js\";\nexport {\n ClaudeCodeLauncher,\n buildClaudeCodeAppleScript,\n type ClaudeCodeExecOptions,\n type ClaudeCodeExecResult,\n type ClaudeCodeLauncherLike,\n type ClaudeCodeLauncherOptions,\n type ClaudeCodePreflightResult,\n type ClaudeCodePreflightValue,\n type ClaudeCodeProcessRunner,\n} from \"./claude.js\";\nexport {\n CursorLauncher,\n type CursorChildProcess,\n type CursorLauncherLike,\n type CursorLauncherOptions,\n type CursorSpawn,\n type CursorSpawnOptions,\n} from \"./cursor.js\";\nexport {\n PathExecutableResolver,\n type ExecutableAccess,\n type ExecutableResolverLike,\n type ExecutableResolverOptions,\n} from \"./executable.js\";\nexport {\n PrototypePreferences,\n PrototypePreferencesError,\n type PrototypePreferencesErrorCode,\n type PrototypePreferencesLike,\n type PrototypePreferencesOptions,\n} from \"./preferences.js\";\nexport type {\n PreparePrototypeFiles,\n PreparePrototypeFilesRequest,\n} from \"./prepare-prototype-files.js\";\nexport {\n LocalPrototypeLifecycle,\n type LocalPrototypeLifecycleOptions,\n type PrototypeLifecycle,\n} from \"./lifecycle/local-prototype-lifecycle.js\";\nexport {\n assertIdentityBranchReady,\n hasUnresolvedRepositoryOperation,\n synchronizeIdentityBranch,\n type RepositorySynchronizationResult,\n type SynchronizationDeferredReason,\n type SynchronizationUnsafeReason,\n type SynchronizeIdentityBranchOptions,\n} from \"./lifecycle/repository-synchronization.js\";\nexport {\n getRepositorySummary,\n type RepositorySummaryOptions,\n} from \"./lifecycle/repository-summary.js\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,uBAAuB,EACvB,KAAK,+BAA+B,EACpC,KAAK,kBAAkB,EACvB,KAAK,2BAA2B,EAChC,KAAK,wBAAwB,GAC9B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,eAAe,EACf,cAAc,EACd,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,GACvB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,gBAAgB,EAChB,KAAK,oBAAoB,GAC1B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,4BAA4B,EAC5B,KAAK,uBAAuB,EAC5B,KAAK,6BAA6B,GACnC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,qBAAqB,EACrB,KAAK,yBAAyB,EAC9B,KAAK,4BAA4B,GAClC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,kBAAkB,EAClB,0BAA0B,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,EAC9B,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,GAC7B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,cAAc,EACd,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,WAAW,EAChB,KAAK,kBAAkB,GACxB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,sBAAsB,EACtB,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,GAC/B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,oBAAoB,EACpB,yBAAyB,EACzB,KAAK,6BAA6B,EAClC,KAAK,wBAAwB,EAC7B,KAAK,2BAA2B,GACjC,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,qBAAqB,EACrB,4BAA4B,GAC7B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,uBAAuB,EACvB,KAAK,8BAA8B,EACnC,KAAK,kBAAkB,GACxB,MAAM,0CAA0C,CAAC;AAClD,OAAO,EACL,yBAAyB,EACzB,gCAAgC,EAChC,yBAAyB,EACzB,KAAK,+BAA+B,EACpC,KAAK,6BAA6B,EAClC,KAAK,2BAA2B,EAChC,KAAK,gCAAgC,GACtC,MAAM,2CAA2C,CAAC;AACnD,OAAO,EACL,oBAAoB,EACpB,KAAK,wBAAwB,GAC9B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,EACtB,KAAK,mBAAmB,GACzB,MAAM,mCAAmC,CAAC","sourcesContent":["export {\n createDeploymentProvider,\n DeploymentProviderError,\n type CreateDeploymentProviderOptions,\n type DeploymentProvider,\n type DeploymentProviderErrorKind,\n type DeploymentProviderResult,\n} from \"./deployment-provider.js\";\nexport {\n GitHubCliClient,\n GitHubCliError,\n type GitHubCliClientLike,\n type GitHubCliClientOptions,\n type GitHubCliErrorReason,\n type GitHubCliWebLogin,\n} from \"./github-cli.js\";\nexport type {\n GitHubCliChildProcess,\n GitHubCliExecOptions,\n GitHubCliExecResult,\n GitHubCliOutputStream,\n GitHubCliProcessRunner,\n GitHubCliSpawnOptions,\n} from \"./process-runner.js\";\nexport {\n PrototypeCatalog,\n type PrototypeCatalogLike,\n} from \"./prototype-catalog.js\";\nexport {\n resolvePrototypeCatalogPaths,\n type PrototypeCatalogOptions,\n type ResolvedPrototypeCatalogPaths,\n} from \"./prototype-paths.js\";\nexport {\n PrototypeAgentService,\n type PrototypeAgentServiceLike,\n type PrototypeAgentServiceOptions,\n} from \"./agent-service.js\";\nexport {\n ClaudeCodeLauncher,\n buildClaudeCodeAppleScript,\n type ClaudeCodeExecOptions,\n type ClaudeCodeExecResult,\n type ClaudeCodeLauncherLike,\n type ClaudeCodeLauncherOptions,\n type ClaudeCodePreflightResult,\n type ClaudeCodePreflightValue,\n type ClaudeCodeProcessRunner,\n} from \"./claude.js\";\nexport {\n CursorLauncher,\n type CursorChildProcess,\n type CursorLauncherLike,\n type CursorLauncherOptions,\n type CursorSpawn,\n type CursorSpawnOptions,\n} from \"./cursor.js\";\nexport {\n PathExecutableResolver,\n type ExecutableAccess,\n type ExecutableResolverLike,\n type ExecutableResolverOptions,\n} from \"./executable.js\";\nexport {\n PrototypePreferences,\n PrototypePreferencesError,\n type PrototypePreferencesErrorCode,\n type PrototypePreferencesLike,\n type PrototypePreferencesOptions,\n} from \"./preferences.js\";\nexport type {\n PreparePrototypeFiles,\n PreparePrototypeFilesRequest,\n} from \"./prepare-prototype-files.js\";\nexport {\n LocalPrototypeLifecycle,\n type LocalPrototypeLifecycleOptions,\n type PrototypeLifecycle,\n} from \"./lifecycle/local-prototype-lifecycle.js\";\nexport {\n assertIdentityBranchReady,\n hasUnresolvedRepositoryOperation,\n synchronizeIdentityBranch,\n type RepositorySynchronizationResult,\n type SynchronizationDeferredReason,\n type SynchronizationUnsafeReason,\n type SynchronizeIdentityBranchOptions,\n} from \"./lifecycle/repository-synchronization.js\";\nexport {\n getRepositorySummary,\n type RepositorySummaryOptions,\n} from \"./lifecycle/repository-summary.js\";\nexport {\n clearPreparationMarker,\n hasPreparationMarker,\n preparationMarkerPath,\n readPreparationMarker,\n writePreparationMarker,\n type DependencyInstaller,\n} from \"./lifecycle/preparation-marker.js\";\n"]}
|
package/dist/index.js
CHANGED
|
@@ -10,4 +10,5 @@ export { PrototypePreferences, PrototypePreferencesError, } from "./preferences.
|
|
|
10
10
|
export { LocalPrototypeLifecycle, } from "./lifecycle/local-prototype-lifecycle.js";
|
|
11
11
|
export { assertIdentityBranchReady, hasUnresolvedRepositoryOperation, synchronizeIdentityBranch, } from "./lifecycle/repository-synchronization.js";
|
|
12
12
|
export { getRepositorySummary, } from "./lifecycle/repository-summary.js";
|
|
13
|
+
export { clearPreparationMarker, hasPreparationMarker, preparationMarkerPath, readPreparationMarker, writePreparationMarker, } from "./lifecycle/preparation-marker.js";
|
|
13
14
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,uBAAuB,GAKxB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,eAAe,EACf,cAAc,GAKf,MAAM,iBAAiB,CAAC;AASzB,OAAO,EACL,gBAAgB,GAEjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,4BAA4B,GAG7B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,qBAAqB,GAGtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,kBAAkB,EAClB,0BAA0B,GAQ3B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,cAAc,GAMf,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,sBAAsB,GAIvB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,oBAAoB,EACpB,yBAAyB,GAI1B,MAAM,kBAAkB,CAAC;AAK1B,OAAO,EACL,uBAAuB,GAGxB,MAAM,0CAA0C,CAAC;AAClD,OAAO,EACL,yBAAyB,EACzB,gCAAgC,EAChC,yBAAyB,GAK1B,MAAM,2CAA2C,CAAC;AACnD,OAAO,EACL,oBAAoB,GAErB,MAAM,mCAAmC,CAAC","sourcesContent":["export {\n createDeploymentProvider,\n DeploymentProviderError,\n type CreateDeploymentProviderOptions,\n type DeploymentProvider,\n type DeploymentProviderErrorKind,\n type DeploymentProviderResult,\n} from \"./deployment-provider.js\";\nexport {\n GitHubCliClient,\n GitHubCliError,\n type GitHubCliClientLike,\n type GitHubCliClientOptions,\n type GitHubCliErrorReason,\n type GitHubCliWebLogin,\n} from \"./github-cli.js\";\nexport type {\n GitHubCliChildProcess,\n GitHubCliExecOptions,\n GitHubCliExecResult,\n GitHubCliOutputStream,\n GitHubCliProcessRunner,\n GitHubCliSpawnOptions,\n} from \"./process-runner.js\";\nexport {\n PrototypeCatalog,\n type PrototypeCatalogLike,\n} from \"./prototype-catalog.js\";\nexport {\n resolvePrototypeCatalogPaths,\n type PrototypeCatalogOptions,\n type ResolvedPrototypeCatalogPaths,\n} from \"./prototype-paths.js\";\nexport {\n PrototypeAgentService,\n type PrototypeAgentServiceLike,\n type PrototypeAgentServiceOptions,\n} from \"./agent-service.js\";\nexport {\n ClaudeCodeLauncher,\n buildClaudeCodeAppleScript,\n type ClaudeCodeExecOptions,\n type ClaudeCodeExecResult,\n type ClaudeCodeLauncherLike,\n type ClaudeCodeLauncherOptions,\n type ClaudeCodePreflightResult,\n type ClaudeCodePreflightValue,\n type ClaudeCodeProcessRunner,\n} from \"./claude.js\";\nexport {\n CursorLauncher,\n type CursorChildProcess,\n type CursorLauncherLike,\n type CursorLauncherOptions,\n type CursorSpawn,\n type CursorSpawnOptions,\n} from \"./cursor.js\";\nexport {\n PathExecutableResolver,\n type ExecutableAccess,\n type ExecutableResolverLike,\n type ExecutableResolverOptions,\n} from \"./executable.js\";\nexport {\n PrototypePreferences,\n PrototypePreferencesError,\n type PrototypePreferencesErrorCode,\n type PrototypePreferencesLike,\n type PrototypePreferencesOptions,\n} from \"./preferences.js\";\nexport type {\n PreparePrototypeFiles,\n PreparePrototypeFilesRequest,\n} from \"./prepare-prototype-files.js\";\nexport {\n LocalPrototypeLifecycle,\n type LocalPrototypeLifecycleOptions,\n type PrototypeLifecycle,\n} from \"./lifecycle/local-prototype-lifecycle.js\";\nexport {\n assertIdentityBranchReady,\n hasUnresolvedRepositoryOperation,\n synchronizeIdentityBranch,\n type RepositorySynchronizationResult,\n type SynchronizationDeferredReason,\n type SynchronizationUnsafeReason,\n type SynchronizeIdentityBranchOptions,\n} from \"./lifecycle/repository-synchronization.js\";\nexport {\n getRepositorySummary,\n type RepositorySummaryOptions,\n} from \"./lifecycle/repository-summary.js\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,uBAAuB,GAKxB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,eAAe,EACf,cAAc,GAKf,MAAM,iBAAiB,CAAC;AASzB,OAAO,EACL,gBAAgB,GAEjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,4BAA4B,GAG7B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,qBAAqB,GAGtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,kBAAkB,EAClB,0BAA0B,GAQ3B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,cAAc,GAMf,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,sBAAsB,GAIvB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,oBAAoB,EACpB,yBAAyB,GAI1B,MAAM,kBAAkB,CAAC;AAK1B,OAAO,EACL,uBAAuB,GAGxB,MAAM,0CAA0C,CAAC;AAClD,OAAO,EACL,yBAAyB,EACzB,gCAAgC,EAChC,yBAAyB,GAK1B,MAAM,2CAA2C,CAAC;AACnD,OAAO,EACL,oBAAoB,GAErB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,GAEvB,MAAM,mCAAmC,CAAC","sourcesContent":["export {\n createDeploymentProvider,\n DeploymentProviderError,\n type CreateDeploymentProviderOptions,\n type DeploymentProvider,\n type DeploymentProviderErrorKind,\n type DeploymentProviderResult,\n} from \"./deployment-provider.js\";\nexport {\n GitHubCliClient,\n GitHubCliError,\n type GitHubCliClientLike,\n type GitHubCliClientOptions,\n type GitHubCliErrorReason,\n type GitHubCliWebLogin,\n} from \"./github-cli.js\";\nexport type {\n GitHubCliChildProcess,\n GitHubCliExecOptions,\n GitHubCliExecResult,\n GitHubCliOutputStream,\n GitHubCliProcessRunner,\n GitHubCliSpawnOptions,\n} from \"./process-runner.js\";\nexport {\n PrototypeCatalog,\n type PrototypeCatalogLike,\n} from \"./prototype-catalog.js\";\nexport {\n resolvePrototypeCatalogPaths,\n type PrototypeCatalogOptions,\n type ResolvedPrototypeCatalogPaths,\n} from \"./prototype-paths.js\";\nexport {\n PrototypeAgentService,\n type PrototypeAgentServiceLike,\n type PrototypeAgentServiceOptions,\n} from \"./agent-service.js\";\nexport {\n ClaudeCodeLauncher,\n buildClaudeCodeAppleScript,\n type ClaudeCodeExecOptions,\n type ClaudeCodeExecResult,\n type ClaudeCodeLauncherLike,\n type ClaudeCodeLauncherOptions,\n type ClaudeCodePreflightResult,\n type ClaudeCodePreflightValue,\n type ClaudeCodeProcessRunner,\n} from \"./claude.js\";\nexport {\n CursorLauncher,\n type CursorChildProcess,\n type CursorLauncherLike,\n type CursorLauncherOptions,\n type CursorSpawn,\n type CursorSpawnOptions,\n} from \"./cursor.js\";\nexport {\n PathExecutableResolver,\n type ExecutableAccess,\n type ExecutableResolverLike,\n type ExecutableResolverOptions,\n} from \"./executable.js\";\nexport {\n PrototypePreferences,\n PrototypePreferencesError,\n type PrototypePreferencesErrorCode,\n type PrototypePreferencesLike,\n type PrototypePreferencesOptions,\n} from \"./preferences.js\";\nexport type {\n PreparePrototypeFiles,\n PreparePrototypeFilesRequest,\n} from \"./prepare-prototype-files.js\";\nexport {\n LocalPrototypeLifecycle,\n type LocalPrototypeLifecycleOptions,\n type PrototypeLifecycle,\n} from \"./lifecycle/local-prototype-lifecycle.js\";\nexport {\n assertIdentityBranchReady,\n hasUnresolvedRepositoryOperation,\n synchronizeIdentityBranch,\n type RepositorySynchronizationResult,\n type SynchronizationDeferredReason,\n type SynchronizationUnsafeReason,\n type SynchronizeIdentityBranchOptions,\n} from \"./lifecycle/repository-synchronization.js\";\nexport {\n getRepositorySummary,\n type RepositorySummaryOptions,\n} from \"./lifecycle/repository-summary.js\";\nexport {\n clearPreparationMarker,\n hasPreparationMarker,\n preparationMarkerPath,\n readPreparationMarker,\n writePreparationMarker,\n type DependencyInstaller,\n} from \"./lifecycle/preparation-marker.js\";\n"]}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { PrototypeMetadata, PrototypeRef } from "@ebay-dt/bonfire-core";
|
|
2
2
|
export declare const GENERATED_FILES: readonly ["page.tsx", "app.tsx", "app.module.css", "components/.gitkeep", "metadata.json", "tsconfig.json", "css-modules.d.ts"];
|
|
3
|
-
export declare const COPYABLE_IMPLEMENTATION_FILES: readonly ["page.tsx", "app.tsx", "app.module.css"];
|
|
4
3
|
export declare function buildPageTsx(): string;
|
|
5
4
|
export declare function buildAppTsx(title: string, description: string | null, ref: PrototypeRef): string;
|
|
6
5
|
export declare function buildAppCss(): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prototype-templates.d.ts","sourceRoot":"","sources":["../../src/internal/prototype-templates.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE7E,eAAO,MAAM,eAAe,YAC1B,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,qBAAqB,EACrB,eAAe,EACf,eAAe,EACf,kBAAkB,CACV,CAAC;AAEX,
|
|
1
|
+
{"version":3,"file":"prototype-templates.d.ts","sourceRoot":"","sources":["../../src/internal/prototype-templates.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE7E,eAAO,MAAM,eAAe,YAC1B,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,qBAAqB,EACrB,eAAe,EACf,eAAe,EACf,kBAAkB,CACV,CAAC;AAEX,wBAAgB,YAAY,WAO3B;AAED,wBAAgB,WAAW,CACzB,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,GAAG,EAAE,YAAY,UAsBlB;AAED,wBAAgB,WAAW,WAS1B;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,GAAG,IAAI,EACzB,SAAS,EAAE,MAAM,EACjB,KAAK,CAAC,EAAE,iBAAiB,CAAC,OAAO,CAAC,UAanC;AAED,wBAAgB,aAAa,CAAC,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,UAMxE;AAED,wBAAgB,0BAA0B,WAMzC","sourcesContent":["import { join, relative, sep } from \"node:path\";\nimport type { PrototypeMetadata, PrototypeRef } from \"@ebay-dt/bonfire-core\";\n\nexport const GENERATED_FILES = [\n \"page.tsx\",\n \"app.tsx\",\n \"app.module.css\",\n \"components/.gitkeep\",\n \"metadata.json\",\n \"tsconfig.json\",\n \"css-modules.d.ts\",\n] as const;\n\nexport function buildPageTsx() {\n return `import App from \"./app\";\n\nexport default function Page() {\n return <App />;\n}\n`;\n}\n\nexport function buildAppTsx(\n title: string,\n description: string | null,\n ref: PrototypeRef,\n) {\n return `\"use client\";\n\nimport { PrototypeOnboardingCard } from \"@ebay-dt/bonfire-react\";\nimport styles from \"./app.module.css\";\n\nexport default function App() {\n return (\n <main className={styles.container}>\n <PrototypeOnboardingCard\n title={${JSON.stringify(title)}}\n description={${JSON.stringify(description)}}\n prototypeRef={{\n login: ${JSON.stringify(ref.login)},\n slug: ${JSON.stringify(ref.slug)},\n }}\n />\n </main>\n );\n}\n`;\n}\n\nexport function buildAppCss() {\n return `.container {\n display: grid;\n gap: 1rem;\n min-block-size: calc(100svh - var(--app-header-block-size, 0));\n place-content: center;\n padding: 2rem;\n}\n`;\n}\n\nexport function buildMetadataJson(\n title: string,\n description: string | null,\n authorLogin: string,\n authorName: string | null,\n timestamp: string,\n theme?: PrototypeMetadata[\"theme\"],\n) {\n const metadata: PrototypeMetadata = {\n title,\n description,\n authorLogin,\n authorName,\n createdAt: timestamp,\n updatedAt: timestamp,\n previewUrl: null,\n ...(theme === undefined ? {} : { theme }),\n };\n return `${JSON.stringify(metadata, null, 2)}\\n`;\n}\n\nexport function buildTsConfig(repositoryRoot: string, destination: string) {\n const relativeRepositoryRoot = relative(destination, repositoryRoot);\n const extension = join(relativeRepositoryRoot, \"tsconfig.json\")\n .split(sep)\n .join(\"/\");\n return `${JSON.stringify({ extends: extension }, null, 2)}\\n`;\n}\n\nexport function buildCssModulesDeclaration() {\n return `declare module \"*.module.css\" {\n const classes: Record<string, string>;\n export default classes;\n}\n`;\n}\n"]}
|
|
@@ -8,11 +8,6 @@ export const GENERATED_FILES = [
|
|
|
8
8
|
"tsconfig.json",
|
|
9
9
|
"css-modules.d.ts",
|
|
10
10
|
];
|
|
11
|
-
export const COPYABLE_IMPLEMENTATION_FILES = [
|
|
12
|
-
"page.tsx",
|
|
13
|
-
"app.tsx",
|
|
14
|
-
"app.module.css",
|
|
15
|
-
];
|
|
16
11
|
export function buildPageTsx() {
|
|
17
12
|
return `import App from "./app";
|
|
18
13
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prototype-templates.js","sourceRoot":"","sources":["../../src/internal/prototype-templates.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAGhD,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,UAAU;IACV,SAAS;IACT,gBAAgB;IAChB,qBAAqB;IACrB,eAAe;IACf,eAAe;IACf,kBAAkB;CACV,CAAC;AAEX,MAAM,
|
|
1
|
+
{"version":3,"file":"prototype-templates.js","sourceRoot":"","sources":["../../src/internal/prototype-templates.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAGhD,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,UAAU;IACV,SAAS;IACT,gBAAgB;IAChB,qBAAqB;IACrB,eAAe;IACf,eAAe;IACf,kBAAkB;CACV,CAAC;AAEX,MAAM,UAAU,YAAY;IAC1B,OAAO;;;;;CAKR,CAAC;AACF,CAAC;AAED,MAAM,UAAU,WAAW,CACzB,KAAa,EACb,WAA0B,EAC1B,GAAiB;IAEjB,OAAO;;;;;;;;;iBASQ,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;uBACf,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC;;mBAE/B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;kBAC1B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;;;;;;CAMzC,CAAC;AACF,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO;;;;;;;CAOR,CAAC;AACF,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,KAAa,EACb,WAA0B,EAC1B,WAAmB,EACnB,UAAyB,EACzB,SAAiB,EACjB,KAAkC;IAElC,MAAM,QAAQ,GAAsB;QAClC,KAAK;QACL,WAAW;QACX,WAAW;QACX,UAAU;QACV,SAAS,EAAE,SAAS;QACpB,SAAS,EAAE,SAAS;QACpB,UAAU,EAAE,IAAI;QAChB,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;KAC1C,CAAC;IACF,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,cAAsB,EAAE,WAAmB;IACvE,MAAM,sBAAsB,GAAG,QAAQ,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IACrE,MAAM,SAAS,GAAG,IAAI,CAAC,sBAAsB,EAAE,eAAe,CAAC;SAC5D,KAAK,CAAC,GAAG,CAAC;SACV,IAAI,CAAC,GAAG,CAAC,CAAC;IACb,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,0BAA0B;IACxC,OAAO;;;;CAIR,CAAC;AACF,CAAC","sourcesContent":["import { join, relative, sep } from \"node:path\";\nimport type { PrototypeMetadata, PrototypeRef } from \"@ebay-dt/bonfire-core\";\n\nexport const GENERATED_FILES = [\n \"page.tsx\",\n \"app.tsx\",\n \"app.module.css\",\n \"components/.gitkeep\",\n \"metadata.json\",\n \"tsconfig.json\",\n \"css-modules.d.ts\",\n] as const;\n\nexport function buildPageTsx() {\n return `import App from \"./app\";\n\nexport default function Page() {\n return <App />;\n}\n`;\n}\n\nexport function buildAppTsx(\n title: string,\n description: string | null,\n ref: PrototypeRef,\n) {\n return `\"use client\";\n\nimport { PrototypeOnboardingCard } from \"@ebay-dt/bonfire-react\";\nimport styles from \"./app.module.css\";\n\nexport default function App() {\n return (\n <main className={styles.container}>\n <PrototypeOnboardingCard\n title={${JSON.stringify(title)}}\n description={${JSON.stringify(description)}}\n prototypeRef={{\n login: ${JSON.stringify(ref.login)},\n slug: ${JSON.stringify(ref.slug)},\n }}\n />\n </main>\n );\n}\n`;\n}\n\nexport function buildAppCss() {\n return `.container {\n display: grid;\n gap: 1rem;\n min-block-size: calc(100svh - var(--app-header-block-size, 0));\n place-content: center;\n padding: 2rem;\n}\n`;\n}\n\nexport function buildMetadataJson(\n title: string,\n description: string | null,\n authorLogin: string,\n authorName: string | null,\n timestamp: string,\n theme?: PrototypeMetadata[\"theme\"],\n) {\n const metadata: PrototypeMetadata = {\n title,\n description,\n authorLogin,\n authorName,\n createdAt: timestamp,\n updatedAt: timestamp,\n previewUrl: null,\n ...(theme === undefined ? {} : { theme }),\n };\n return `${JSON.stringify(metadata, null, 2)}\\n`;\n}\n\nexport function buildTsConfig(repositoryRoot: string, destination: string) {\n const relativeRepositoryRoot = relative(destination, repositoryRoot);\n const extension = join(relativeRepositoryRoot, \"tsconfig.json\")\n .split(sep)\n .join(\"/\");\n return `${JSON.stringify({ extends: extension }, null, 2)}\\n`;\n}\n\nexport function buildCssModulesDeclaration() {\n return `declare module \"*.module.css\" {\n const classes: Record<string, string>;\n export default classes;\n}\n`;\n}\n"]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type GitCommitIdentity, type GitRepository } from "../git-repository.js";
|
|
2
|
+
type DeploymentPhase = "publication";
|
|
3
|
+
type DeploymentStep = "fetch" | "directory" | "marker" | "worktree-add" | "source-verify" | "namespace-read" | "namespace-write" | "namespace-commit" | "metadata-read" | "metadata-write" | "metadata-commit" | "push" | "remote-confirm" | "cleanup";
|
|
4
|
+
export type DeploymentWorktreeOptions = {
|
|
5
|
+
remote: string;
|
|
6
|
+
primaryBranch: string;
|
|
7
|
+
sourceSha: string;
|
|
8
|
+
namespacePath: string;
|
|
9
|
+
timeoutMs?: number;
|
|
10
|
+
commitIdentity?: GitCommitIdentity;
|
|
11
|
+
};
|
|
12
|
+
export type DeploymentWorktreeErrorKind = "invalid-source" | "protected-path" | "metadata-failure" | "publication-rejected" | "publication-failure" | "cleanup-failure";
|
|
13
|
+
/** Log only finite classifications; Git/OS messages may contain paths or credentials. */
|
|
14
|
+
export declare function reportDeploymentIssue(phase: DeploymentPhase, step: DeploymentStep, error: unknown): void;
|
|
15
|
+
export declare class DeploymentWorktreeError extends Error {
|
|
16
|
+
readonly kind: DeploymentWorktreeErrorKind;
|
|
17
|
+
readonly cleanupFailed: boolean;
|
|
18
|
+
readonly operationError: unknown;
|
|
19
|
+
readonly cause: unknown;
|
|
20
|
+
constructor(kind: DeploymentWorktreeErrorKind, options?: {
|
|
21
|
+
cleanupFailed?: boolean;
|
|
22
|
+
operationError?: unknown;
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
export type DeploymentPublicationResult = {
|
|
26
|
+
attempts: 1 | 2;
|
|
27
|
+
cleanupFailed: boolean;
|
|
28
|
+
publicationSha: string;
|
|
29
|
+
};
|
|
30
|
+
export declare function publishDeploymentSource(repository: GitRepository, options: DeploymentWorktreeOptions, prepare: (workspace: {
|
|
31
|
+
path: string;
|
|
32
|
+
repository: GitRepository;
|
|
33
|
+
}) => Promise<void>): Promise<DeploymentPublicationResult>;
|
|
34
|
+
export declare function deploymentWorktreeRelativePath(repositoryRoot: string, workspacePath: string): string;
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=deployment-worktree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deployment-worktree.d.ts","sourceRoot":"","sources":["../../src/lifecycle/deployment-worktree.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,iBAAiB,EACtB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAS9B,KAAK,eAAe,GAAG,aAAa,CAAC;AACrC,KAAK,cAAc,GACf,OAAO,GACP,WAAW,GACX,QAAQ,GACR,cAAc,GACd,eAAe,GACf,gBAAgB,GAChB,iBAAiB,GACjB,kBAAkB,GAClB,eAAe,GACf,gBAAgB,GAChB,iBAAiB,GACjB,MAAM,GACN,gBAAgB,GAChB,SAAS,CAAC;AAEd,MAAM,MAAM,yBAAyB,GAAG;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,iBAAiB,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,2BAA2B,GACnC,gBAAgB,GAChB,gBAAgB,GAChB,kBAAkB,GAClB,sBAAsB,GACtB,qBAAqB,GACrB,iBAAiB,CAAC;AAEtB,yFAAyF;AACzF,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,eAAe,EACtB,IAAI,EAAE,cAAc,EACpB,KAAK,EAAE,OAAO,QAkBf;AAED,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,QAAQ,CAAC,IAAI,EAAE,2BAA2B,CAAC;IAC3C,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IAExB,YACE,IAAI,EAAE,2BAA2B,EACjC,OAAO,GAAE;QAAE,aAAa,CAAC,EAAE,OAAO,CAAC;QAAC,cAAc,CAAC,EAAE,OAAO,CAAA;KAAO,EAQpE;CACF;AAkdD,MAAM,MAAM,2BAA2B,GAAG;IACxC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC;IAChB,aAAa,EAAE,OAAO,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,aAAa,EACzB,OAAO,EAAE,yBAAyB,EAClC,OAAO,EAAE,CAAC,SAAS,EAAE;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,aAAa,CAAC;CAC3B,KAAK,OAAO,CAAC,IAAI,CAAC,GAClB,OAAO,CAAC,2BAA2B,CAAC,CA8FtC;AAED,wBAAgB,8BAA8B,CAC5C,cAAc,EAAE,MAAM,EACtB,aAAa,EAAE,MAAM,UAGtB","sourcesContent":["import { lstat, mkdtemp, readFile, rm, writeFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { isAbsolute, join, relative, sep } from \"node:path\";\nimport {\n createGitRepository,\n GitRepositoryError,\n type GitCommitIdentity,\n type GitRepository,\n} from \"../git-repository.js\";\nimport {\n isProtectedPrototypePath,\n isRegularPrototypeMode,\n} from \"./prototype-path-policy.js\";\n\nconst OWNERSHIP_MARKER = \"bonfire deployment workspace\\n\";\nconst SOURCE_SHA_PATTERN = /^[0-9a-f]{40,64}$/u;\n\ntype DeploymentPhase = \"publication\";\ntype DeploymentStep =\n | \"fetch\"\n | \"directory\"\n | \"marker\"\n | \"worktree-add\"\n | \"source-verify\"\n | \"namespace-read\"\n | \"namespace-write\"\n | \"namespace-commit\"\n | \"metadata-read\"\n | \"metadata-write\"\n | \"metadata-commit\"\n | \"push\"\n | \"remote-confirm\"\n | \"cleanup\";\n\nexport type DeploymentWorktreeOptions = {\n remote: string;\n primaryBranch: string;\n sourceSha: string;\n namespacePath: string;\n timeoutMs?: number;\n commitIdentity?: GitCommitIdentity;\n};\n\nexport type DeploymentWorktreeErrorKind =\n | \"invalid-source\"\n | \"protected-path\"\n | \"metadata-failure\"\n | \"publication-rejected\"\n | \"publication-failure\"\n | \"cleanup-failure\";\n\n/** Log only finite classifications; Git/OS messages may contain paths or credentials. */\nexport function reportDeploymentIssue(\n phase: DeploymentPhase,\n step: DeploymentStep,\n error: unknown,\n) {\n const kind =\n step.startsWith(\"metadata-\") ||\n step.startsWith(\"namespace-\") ||\n step === \"directory\" ||\n step === \"marker\"\n ? \"filesystem-failure\"\n : error instanceof GitRepositoryError\n ? error.kind\n : error instanceof DeploymentWorktreeError\n ? error.kind\n : \"unexpected\";\n console.warn(\"[bonfire] Deployment workspace attention\", {\n phase,\n step,\n kind,\n });\n}\n\nexport class DeploymentWorktreeError extends Error {\n readonly kind: DeploymentWorktreeErrorKind;\n readonly cleanupFailed: boolean;\n readonly operationError: unknown;\n readonly cause: unknown;\n\n constructor(\n kind: DeploymentWorktreeErrorKind,\n options: { cleanupFailed?: boolean; operationError?: unknown } = {},\n ) {\n super(`Deployment workspace operation failed: ${kind}`);\n this.name = \"DeploymentWorktreeError\";\n this.kind = kind;\n this.cleanupFailed = options.cleanupFailed ?? false;\n this.operationError = options.operationError;\n this.cause = options.operationError;\n }\n}\n\nfunction withCleanupFailure(error: unknown): DeploymentWorktreeError {\n if (error instanceof DeploymentWorktreeError) {\n return new DeploymentWorktreeError(error.kind, {\n cleanupFailed: true,\n operationError: error.operationError ?? error,\n });\n }\n return new DeploymentWorktreeError(\"cleanup-failure\", {\n cleanupFailed: true,\n operationError: error,\n });\n}\n\ntype DeploymentWorktree = {\n path: string;\n repository: GitRepository;\n cleanup(): Promise<void>;\n};\n\ntype DeploymentWorkspaceOperation<Value> = (\n workspace: DeploymentWorktree,\n) => Promise<Value>;\n\ntype TreeEntry = {\n path: string;\n mode: string;\n};\n\nfunction assertBranchName(value: string, option: string) {\n if (\n value.length === 0 ||\n value.startsWith(\"-\") ||\n value.includes(\"\\0\") ||\n /\\s/u.test(value) ||\n value.includes(\"@{\") ||\n value.split(/[\\\\/]/u).some((segment) => segment === \"..\")\n ) {\n throw new TypeError(`Invalid ${option}`);\n }\n}\n\nfunction assertSourceSha(sourceSha: string) {\n if (!SOURCE_SHA_PATTERN.test(sourceSha)) {\n throw new DeploymentWorktreeError(\"invalid-source\");\n }\n}\n\nfunction assertNamespacePath(namespacePath: string) {\n if (\n namespacePath.length === 0 ||\n namespacePath === \".\" ||\n isAbsolute(namespacePath) ||\n namespacePath.startsWith(\"-\") ||\n namespacePath.includes(\"\\0\") ||\n namespacePath.includes(\"\\\\\") ||\n namespacePath.includes(\":\") ||\n /[*?\\[\\]]/u.test(namespacePath) ||\n namespacePath\n .split(\"/\")\n .some((segment) => segment.length === 0 || segment === \"..\")\n ) {\n throw new DeploymentWorktreeError(\"protected-path\");\n }\n}\n\nfunction remotePrimaryRef(options: DeploymentWorktreeOptions) {\n return `refs/remotes/${options.remote}/${options.primaryBranch}`;\n}\n\nfunction parseTreeEntries(output: string): TreeEntry[] {\n return output\n .split(\"\\0\")\n .filter(Boolean)\n .flatMap((entry) => {\n const tab = entry.indexOf(\"\\t\");\n if (tab < 0) return [];\n const header = entry.slice(0, tab).split(/\\s+/u);\n const mode = header[0];\n const path = entry.slice(tab + 1).replaceAll(\"\\\\\", \"/\");\n if (mode === undefined || path.length === 0) return [];\n return [{ mode, path }];\n });\n}\n\nasync function readTreeEntries(\n repository: GitRepository,\n ref: string,\n namespacePath: string,\n) {\n const output = await repository.raw([\n \"ls-tree\",\n \"-r\",\n \"-z\",\n \"--full-tree\",\n ref,\n \"--\",\n namespacePath,\n ]);\n return parseTreeEntries(output);\n}\n\nfunction pathIsWithin(path: string, parent: string) {\n return path === parent || path.startsWith(`${parent}/`);\n}\n\nfunction isPrototypeRootMetadataPath(path: string, namespacePath: string) {\n if (!path.endsWith(\"/metadata.json\") || !pathIsWithin(path, namespacePath)) {\n return false;\n }\n const relativePath = path.slice(namespacePath.length + 1);\n return relativePath.split(\"/\").length === 2;\n}\n\nfunction assertSafeTree(entries: readonly TreeEntry[], namespacePath: string) {\n for (const entry of entries) {\n if (\n !pathIsWithin(entry.path, namespacePath) ||\n isProtectedPrototypePath(entry.path) ||\n !isRegularPrototypeMode(entry.mode) ||\n entry.mode.startsWith(\"120000\")\n ) {\n throw new DeploymentWorktreeError(\"protected-path\");\n }\n }\n}\n\nfunction parseObject(source: string): Record<string, unknown> | null {\n try {\n const value: unknown = JSON.parse(source);\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return null;\n }\n return { ...(value as Record<string, unknown>) };\n } catch {\n return null;\n }\n}\n\nfunction safePreviewValue(document: Record<string, unknown>) {\n if (!Object.hasOwn(document, \"previewUrl\")) return null;\n const value = document.previewUrl;\n return value === null || typeof value === \"string\" ? value : undefined;\n}\n\nasync function capturePreviewOverlays(\n repository: GitRepository,\n sourceSha: string,\n namespacePath: string,\n sourceEntries: readonly TreeEntry[],\n primaryEntries: readonly TreeEntry[],\n) {\n const primaryPaths = new Set(primaryEntries.map((entry) => entry.path));\n const overlays: Array<{\n path: string;\n source: Record<string, unknown>;\n preview: string | null;\n }> = [];\n for (const entry of sourceEntries) {\n if (\n !isPrototypeRootMetadataPath(entry.path, namespacePath) ||\n !primaryPaths.has(entry.path)\n ) {\n continue;\n }\n const primarySource = await repository.raw([\"show\", `HEAD:${entry.path}`]);\n const primaryDocument = parseObject(primarySource);\n if (primaryDocument === null) {\n throw new DeploymentWorktreeError(\"publication-failure\");\n }\n const preview = safePreviewValue(primaryDocument);\n if (preview === undefined) {\n throw new DeploymentWorktreeError(\"publication-failure\");\n }\n const source = parseObject(\n await repository.raw([\"show\", `${sourceSha}:${entry.path}`]),\n );\n if (source === null) {\n throw new DeploymentWorktreeError(\"publication-failure\");\n }\n if (!pathIsWithin(entry.path, namespacePath)) {\n throw new DeploymentWorktreeError(\"protected-path\");\n }\n overlays.push({ path: entry.path, source, preview });\n }\n return overlays;\n}\n\nasync function composeOwnedNamespace(\n workspace: DeploymentWorktree,\n options: DeploymentWorktreeOptions,\n) {\n const step = \"namespace-read\" as const;\n let sourceEntries: TreeEntry[];\n let primaryEntries: TreeEntry[];\n try {\n sourceEntries = await readTreeEntries(\n workspace.repository,\n options.sourceSha,\n options.namespacePath,\n );\n primaryEntries = await readTreeEntries(\n workspace.repository,\n \"HEAD\",\n options.namespacePath,\n );\n assertSafeTree(sourceEntries, options.namespacePath);\n assertSafeTree(primaryEntries, options.namespacePath);\n } catch (error) {\n reportDeploymentIssue(\"publication\", step, error);\n if (error instanceof DeploymentWorktreeError) throw error;\n throw new DeploymentWorktreeError(\"publication-failure\", {\n operationError: error,\n });\n }\n\n let overlays: Awaited<ReturnType<typeof capturePreviewOverlays>>;\n try {\n overlays = await capturePreviewOverlays(\n workspace.repository,\n options.sourceSha,\n options.namespacePath,\n sourceEntries,\n primaryEntries,\n );\n } catch (error) {\n reportDeploymentIssue(\"publication\", \"metadata-read\", error);\n if (error instanceof DeploymentWorktreeError) {\n if (error.kind === \"publication-failure\") {\n throw new DeploymentWorktreeError(\"metadata-failure\", {\n operationError: error,\n });\n }\n throw error;\n }\n throw new DeploymentWorktreeError(\"metadata-failure\", {\n operationError: error,\n });\n }\n\n try {\n await workspace.repository.raw([\n \"rm\",\n \"-r\",\n \"--ignore-unmatch\",\n \"--\",\n options.namespacePath,\n ]);\n if (sourceEntries.length > 0) {\n await workspace.repository.raw([\n \"checkout\",\n options.sourceSha,\n \"--\",\n options.namespacePath,\n ]);\n }\n\n const overlayPaths: string[] = [];\n for (const overlay of overlays) {\n const absolutePath = join(workspace.path, overlay.path);\n const currentSource = await readFile(absolutePath, \"utf8\");\n const currentDocument = parseObject(currentSource);\n if (currentDocument === null) {\n throw new DeploymentWorktreeError(\"publication-failure\");\n }\n await writeFile(\n absolutePath,\n `${JSON.stringify({ ...currentDocument, previewUrl: overlay.preview }, null, 2)}\\n`,\n );\n overlayPaths.push(overlay.path);\n }\n if (overlayPaths.length > 0) {\n await workspace.repository.add(overlayPaths);\n }\n } catch (error) {\n reportDeploymentIssue(\"publication\", \"namespace-write\", error);\n if (error instanceof DeploymentWorktreeError) throw error;\n throw new DeploymentWorktreeError(\"publication-failure\", {\n operationError: error,\n });\n }\n}\n\nasync function createDeploymentWorktree(\n repository: GitRepository,\n options: DeploymentWorktreeOptions,\n): Promise<DeploymentWorktree> {\n assertBranchName(options.remote, \"remote\");\n assertBranchName(options.primaryBranch, \"primary branch\");\n assertSourceSha(options.sourceSha);\n assertNamespacePath(options.namespacePath);\n\n try {\n await repository.fetch(options.remote, options.primaryBranch);\n } catch (error) {\n reportDeploymentIssue(\"publication\", \"fetch\", error);\n throw new DeploymentWorktreeError(\"publication-failure\", {\n operationError: error,\n });\n }\n let operationDirectory: string;\n try {\n operationDirectory = await mkdtemp(join(tmpdir(), \"bonfire-deployment-\"));\n } catch (error) {\n reportDeploymentIssue(\"publication\", \"directory\", error);\n throw new DeploymentWorktreeError(\"publication-failure\", {\n operationError: error,\n });\n }\n const workspacePath = join(operationDirectory, \"workspace\");\n const markerPath = join(operationDirectory, \"OWNER\");\n\n let worktreeAdded = false;\n let step: DeploymentStep = \"marker\";\n try {\n await writeFile(markerPath, OWNERSHIP_MARKER, { flag: \"wx\" });\n step = \"worktree-add\";\n await repository.raw([\n \"worktree\",\n \"add\",\n \"--detach\",\n workspacePath,\n remotePrimaryRef(options),\n ]);\n worktreeAdded = true;\n\n const workspaceRepository = createGitRepository({\n repositoryRoot: workspacePath,\n timeoutMs: options.timeoutMs,\n commitIdentity: options.commitIdentity,\n });\n\n step = \"source-verify\";\n await workspaceRepository.raw([\n \"cat-file\",\n \"-e\",\n `${options.sourceSha}^{commit}`,\n ]);\n\n return {\n path: workspacePath,\n repository: workspaceRepository,\n async cleanup() {\n try {\n const marker = await readFile(markerPath, \"utf8\");\n const stats = await lstat(workspacePath);\n if (marker !== OWNERSHIP_MARKER || stats.isSymbolicLink()) {\n throw new DeploymentWorktreeError(\"cleanup-failure\");\n }\n await repository.raw([\n \"worktree\",\n \"remove\",\n \"--force\",\n workspacePath,\n ]);\n await rm(operationDirectory, { recursive: true, force: false });\n } catch (error) {\n reportDeploymentIssue(\"publication\", \"cleanup\", error);\n if (error instanceof DeploymentWorktreeError) throw error;\n throw new DeploymentWorktreeError(\"cleanup-failure\", {\n operationError: error,\n });\n }\n },\n };\n } catch (error) {\n reportDeploymentIssue(\"publication\", step, error);\n let cleanupFailed = false;\n if (worktreeAdded) {\n try {\n await repository.raw([\"worktree\", \"remove\", \"--force\", workspacePath]);\n } catch (cleanupError) {\n cleanupFailed = true;\n reportDeploymentIssue(\"publication\", \"cleanup\", cleanupError);\n }\n }\n try {\n await rm(operationDirectory, { recursive: true, force: true });\n } catch (cleanupError) {\n cleanupFailed = true;\n reportDeploymentIssue(\"publication\", \"cleanup\", cleanupError);\n }\n throw new DeploymentWorktreeError(\"publication-failure\", {\n cleanupFailed,\n operationError: error,\n });\n }\n}\n\nasync function withDeploymentWorktree<Value>(\n repository: GitRepository,\n options: DeploymentWorktreeOptions,\n operation: DeploymentWorkspaceOperation<Value>,\n): Promise<{ value: Value; cleanupFailed: boolean }> {\n const workspace = await createDeploymentWorktree(repository, options);\n let value: Value;\n try {\n value = await operation(workspace);\n } catch (error) {\n try {\n await workspace.cleanup();\n } catch {\n throw withCleanupFailure(error);\n }\n throw error;\n }\n\n try {\n await workspace.cleanup();\n return { value, cleanupFailed: false };\n } catch {\n return { value, cleanupFailed: true };\n }\n}\n\nfunction mapPushError(error: unknown) {\n if (error instanceof DeploymentWorktreeError) return error;\n if (\n error instanceof GitRepositoryError &&\n error.kind === \"non-fast-forward\"\n ) {\n return new DeploymentWorktreeError(\"publication-rejected\");\n }\n return new DeploymentWorktreeError(\"publication-failure\", {\n operationError: error,\n });\n}\n\nasync function remoteCommit(\n repository: GitRepository,\n options: DeploymentWorktreeOptions,\n) {\n const output = await repository.raw([\n \"ls-remote\",\n options.remote,\n `refs/heads/${options.primaryBranch}`,\n ]);\n const commit = output.trim().split(/\\s+/u)[0];\n return commit !== undefined && SOURCE_SHA_PATTERN.test(commit)\n ? commit.toLowerCase()\n : null;\n}\n\nasync function remoteContainsPublication(\n repository: GitRepository,\n options: DeploymentWorktreeOptions,\n publicationSha: string,\n) {\n const remoteSha = await remoteCommit(repository, options);\n if (remoteSha === publicationSha) return true;\n if (remoteSha === null) return false;\n try {\n // Fetch only updates the repository's remote-tracking ref; it does not\n // modify the active checkout. This recognizes an accepted push followed\n // by a primary descendant without repeating publication work.\n await repository.fetch(options.remote, options.primaryBranch);\n const mergeBase = (\n await repository.raw([\"merge-base\", publicationSha, remoteSha])\n ).trim();\n return mergeBase === publicationSha;\n } catch {\n return false;\n }\n}\n\nexport type DeploymentPublicationResult = {\n attempts: 1 | 2;\n cleanupFailed: boolean;\n publicationSha: string;\n};\n\nexport async function publishDeploymentSource(\n repository: GitRepository,\n options: DeploymentWorktreeOptions,\n prepare: (workspace: {\n path: string;\n repository: GitRepository;\n }) => Promise<void>,\n): Promise<DeploymentPublicationResult> {\n let cleanupFailed = false;\n for (const attempt of [1, 2] as const) {\n try {\n const result = await withDeploymentWorktree(\n repository,\n options,\n async (workspace) => {\n await composeOwnedNamespace(workspace, options);\n await prepare({\n path: workspace.path,\n repository: workspace.repository,\n });\n try {\n await workspace.repository.commit(\n `deploy: publish ${options.sourceSha.slice(0, 12)}`,\n );\n } catch (error) {\n reportDeploymentIssue(\"publication\", \"namespace-commit\", error);\n throw new DeploymentWorktreeError(\"publication-failure\", {\n operationError: error,\n });\n }\n\n const publicationSha = (\n await workspace.repository.raw([\"rev-parse\", \"HEAD\"])\n ).trim();\n try {\n await workspace.repository.raw([\n \"push\",\n options.remote,\n `HEAD:refs/heads/${options.primaryBranch}`,\n ]);\n } catch (error) {\n reportDeploymentIssue(\"publication\", \"push\", error);\n try {\n if (\n await remoteContainsPublication(\n repository,\n options,\n publicationSha,\n )\n ) {\n return { publicationSha };\n }\n } catch (confirmationError) {\n reportDeploymentIssue(\n \"publication\",\n \"remote-confirm\",\n confirmationError,\n );\n }\n throw mapPushError(error);\n }\n return { publicationSha };\n },\n );\n cleanupFailed ||= result.cleanupFailed;\n return {\n attempts: attempt,\n cleanupFailed,\n publicationSha: result.value.publicationSha,\n };\n } catch (error) {\n cleanupFailed ||=\n error instanceof DeploymentWorktreeError && error.cleanupFailed;\n if (\n !(error instanceof DeploymentWorktreeError) ||\n error.kind !== \"publication-rejected\" ||\n attempt === 2\n ) {\n if (cleanupFailed) {\n if (error instanceof DeploymentWorktreeError) {\n if (!error.cleanupFailed) {\n throw new DeploymentWorktreeError(error.kind, {\n cleanupFailed: true,\n operationError: error.operationError ?? error,\n });\n }\n } else {\n throw new DeploymentWorktreeError(\"publication-failure\", {\n cleanupFailed: true,\n operationError: error,\n });\n }\n }\n throw error;\n }\n }\n }\n\n throw new DeploymentWorktreeError(\"publication-rejected\", {\n cleanupFailed,\n });\n}\n\nexport function deploymentWorktreeRelativePath(\n repositoryRoot: string,\n workspacePath: string,\n) {\n return relative(repositoryRoot, workspacePath).split(sep).join(\"/\");\n}\n"]}
|