securewithtrace 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +126 -9
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3564,6 +3564,11 @@ function createAuthCommand() {
|
|
|
3564
3564
|
return auth;
|
|
3565
3565
|
}
|
|
3566
3566
|
|
|
3567
|
+
// src/repo/commands.ts
|
|
3568
|
+
import { chmodSync, mkdtempSync, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
3569
|
+
import { tmpdir } from "os";
|
|
3570
|
+
import { join as join2 } from "path";
|
|
3571
|
+
|
|
3567
3572
|
// ../../node_modules/.bun/@ts-rest+core@3.53.0-rc.1+f9199aabcde8d6a0/node_modules/@ts-rest/core/index.esm.mjs
|
|
3568
3573
|
var util;
|
|
3569
3574
|
(function(util2) {
|
|
@@ -22596,6 +22601,13 @@ var RepositoryResponseSchema = external_exports.object({
|
|
|
22596
22601
|
updatedAt: external_exports.date()
|
|
22597
22602
|
});
|
|
22598
22603
|
var ListRepositoriesResponseSchema = external_exports.array(RepositoryResponseSchema);
|
|
22604
|
+
var CloneTokenRequestSchema = external_exports.object({
|
|
22605
|
+
repositoryUrl: external_exports.string().url()
|
|
22606
|
+
});
|
|
22607
|
+
var CloneTokenResponseSchema = external_exports.object({
|
|
22608
|
+
token: external_exports.string(),
|
|
22609
|
+
expiresAt: external_exports.string().datetime()
|
|
22610
|
+
});
|
|
22599
22611
|
|
|
22600
22612
|
// ../../packages/api-contracts/src/contracts/v1/repository.ts
|
|
22601
22613
|
var c9 = initContract();
|
|
@@ -22661,6 +22673,19 @@ var repositoryContract = c9.router({
|
|
|
22661
22673
|
404: ErrorResponseSchema,
|
|
22662
22674
|
500: ErrorResponseSchema
|
|
22663
22675
|
}
|
|
22676
|
+
},
|
|
22677
|
+
getCloneToken: {
|
|
22678
|
+
method: "POST",
|
|
22679
|
+
path: "/organizations/:organizationId/repositories/clone-token",
|
|
22680
|
+
pathParams: OrgIdParamsSchema,
|
|
22681
|
+
body: CloneTokenRequestSchema,
|
|
22682
|
+
responses: {
|
|
22683
|
+
200: CloneTokenResponseSchema,
|
|
22684
|
+
401: ErrorResponseSchema,
|
|
22685
|
+
403: ErrorResponseSchema,
|
|
22686
|
+
404: ErrorResponseSchema,
|
|
22687
|
+
500: ErrorResponseSchema
|
|
22688
|
+
}
|
|
22664
22689
|
}
|
|
22665
22690
|
});
|
|
22666
22691
|
|
|
@@ -23738,6 +23763,7 @@ var FindingSchema = external_exports.object({
|
|
|
23738
23763
|
});
|
|
23739
23764
|
|
|
23740
23765
|
// src/api-client.ts
|
|
23766
|
+
var readTokenSafe = readToken;
|
|
23741
23767
|
var PRODUCTION_API_URL = "https://api.securewithtrace.com";
|
|
23742
23768
|
function getApiBaseUrl() {
|
|
23743
23769
|
const raw = process.env["TRACE_API_URL"];
|
|
@@ -23799,6 +23825,25 @@ async function resolveOrganizationId(client) {
|
|
|
23799
23825
|
}
|
|
23800
23826
|
return id;
|
|
23801
23827
|
}
|
|
23828
|
+
async function resolveOrganizationIdSafe(client) {
|
|
23829
|
+
try {
|
|
23830
|
+
const result = await client.organization.listOrganizations();
|
|
23831
|
+
if (result.status !== 200) {
|
|
23832
|
+
return null;
|
|
23833
|
+
}
|
|
23834
|
+
const org = result.body[0];
|
|
23835
|
+
if (!org) {
|
|
23836
|
+
return null;
|
|
23837
|
+
}
|
|
23838
|
+
const id = org.organizationId;
|
|
23839
|
+
if (!SAFE_ID_PATTERN.test(id)) {
|
|
23840
|
+
return null;
|
|
23841
|
+
}
|
|
23842
|
+
return id;
|
|
23843
|
+
} catch {
|
|
23844
|
+
return null;
|
|
23845
|
+
}
|
|
23846
|
+
}
|
|
23802
23847
|
|
|
23803
23848
|
// src/repo/commands.ts
|
|
23804
23849
|
function stripAnsi(str) {
|
|
@@ -23879,11 +23924,57 @@ function createListCommand() {
|
|
|
23879
23924
|
}
|
|
23880
23925
|
});
|
|
23881
23926
|
}
|
|
23927
|
+
function urlWithUsername(httpsUrl) {
|
|
23928
|
+
const url2 = new URL(httpsUrl);
|
|
23929
|
+
url2.username = "x-access-token";
|
|
23930
|
+
url2.password = "";
|
|
23931
|
+
return url2.toString();
|
|
23932
|
+
}
|
|
23933
|
+
function createAskPassScript(token) {
|
|
23934
|
+
const dir = mkdtempSync(join2(tmpdir(), "trace-askpass-"));
|
|
23935
|
+
const scriptPath = join2(dir, "askpass.sh");
|
|
23936
|
+
writeFileSync2(scriptPath, `#!/bin/sh
|
|
23937
|
+
echo '${token.replace(/'/g, "'\\''")}'
|
|
23938
|
+
`, {
|
|
23939
|
+
mode: 448
|
|
23940
|
+
});
|
|
23941
|
+
chmodSync(scriptPath, 448);
|
|
23942
|
+
return scriptPath;
|
|
23943
|
+
}
|
|
23944
|
+
async function fetchCloneToken(repoUrl) {
|
|
23945
|
+
const token = readTokenSafe();
|
|
23946
|
+
if (!token) {
|
|
23947
|
+
return null;
|
|
23948
|
+
}
|
|
23949
|
+
try {
|
|
23950
|
+
const client = createClient(token);
|
|
23951
|
+
const organizationId = await resolveOrganizationIdSafe(client);
|
|
23952
|
+
if (!organizationId) {
|
|
23953
|
+
return null;
|
|
23954
|
+
}
|
|
23955
|
+
const result = await client.repository.getCloneToken({
|
|
23956
|
+
params: { organizationId },
|
|
23957
|
+
body: { repositoryUrl: repoUrl }
|
|
23958
|
+
});
|
|
23959
|
+
if (result.status === 200) {
|
|
23960
|
+
return result.body.token;
|
|
23961
|
+
}
|
|
23962
|
+
return null;
|
|
23963
|
+
} catch {
|
|
23964
|
+
return null;
|
|
23965
|
+
}
|
|
23966
|
+
}
|
|
23882
23967
|
function createCloneCommand() {
|
|
23883
23968
|
return new Command("clone").description("Clone a repository").argument("<repository>", "Repository URL or owner/repo shorthand").argument("[directory]", "Directory to clone into").option("--branch <branch>", "Branch to clone").option("--depth <depth>", "Shallow clone depth", Number.parseInt).action(
|
|
23884
23969
|
async (repository, directory, options) => {
|
|
23885
23970
|
const cloneUrl = resolveRepoUrl(repository);
|
|
23886
23971
|
const targetDir = directory ?? extractRepoName(repository);
|
|
23972
|
+
let installationToken = null;
|
|
23973
|
+
if (cloneUrl.startsWith("https://github.com/")) {
|
|
23974
|
+
installationToken = await fetchCloneToken(cloneUrl);
|
|
23975
|
+
}
|
|
23976
|
+
const effectiveUrl = installationToken ? urlWithUsername(cloneUrl) : cloneUrl;
|
|
23977
|
+
let askPassScript;
|
|
23887
23978
|
const args = ["clone"];
|
|
23888
23979
|
if (options.branch) {
|
|
23889
23980
|
validateBranchName(options.branch);
|
|
@@ -23892,17 +23983,43 @@ function createCloneCommand() {
|
|
|
23892
23983
|
if (options.depth !== void 0) {
|
|
23893
23984
|
args.push("--depth", String(options.depth));
|
|
23894
23985
|
}
|
|
23895
|
-
args.push("--",
|
|
23986
|
+
args.push("--", effectiveUrl, targetDir);
|
|
23896
23987
|
console.log(`Cloning ${cloneUrl} into ${targetDir}...`);
|
|
23897
|
-
const
|
|
23898
|
-
|
|
23899
|
-
|
|
23900
|
-
|
|
23901
|
-
|
|
23902
|
-
|
|
23903
|
-
|
|
23988
|
+
const extraEnv = {};
|
|
23989
|
+
if (installationToken) {
|
|
23990
|
+
askPassScript = createAskPassScript(installationToken);
|
|
23991
|
+
extraEnv["GIT_ASKPASS"] = askPassScript;
|
|
23992
|
+
extraEnv["GIT_TERMINAL_PROMPT"] = "0";
|
|
23993
|
+
}
|
|
23994
|
+
try {
|
|
23995
|
+
const proc = Bun.spawn(["git", ...args], {
|
|
23996
|
+
stdout: "inherit",
|
|
23997
|
+
stderr: "inherit",
|
|
23998
|
+
env: { ...process.env, ...extraEnv }
|
|
23999
|
+
});
|
|
24000
|
+
const exitCode = await proc.exited;
|
|
24001
|
+
if (exitCode !== 0) {
|
|
24002
|
+
process.exit(exitCode);
|
|
24003
|
+
}
|
|
24004
|
+
if (installationToken) {
|
|
24005
|
+
const resetProc = Bun.spawn(["git", "remote", "set-url", "origin", cloneUrl], {
|
|
24006
|
+
cwd: targetDir,
|
|
24007
|
+
stdout: "pipe",
|
|
24008
|
+
stderr: "pipe"
|
|
24009
|
+
});
|
|
24010
|
+
const resetExitCode = await resetProc.exited;
|
|
24011
|
+
if (resetExitCode !== 0) {
|
|
24012
|
+
console.error(
|
|
24013
|
+
"Warning: failed to reset remote URL \u2014 the token username may persist in .git/config"
|
|
24014
|
+
);
|
|
24015
|
+
}
|
|
24016
|
+
}
|
|
24017
|
+
console.log(`Repository cloned into ${targetDir}`);
|
|
24018
|
+
} finally {
|
|
24019
|
+
if (askPassScript) {
|
|
24020
|
+
rmSync2(askPassScript.replace(/\/[^/]+$/, ""), { recursive: true, force: true });
|
|
24021
|
+
}
|
|
23904
24022
|
}
|
|
23905
|
-
console.log(`Repository cloned into ${targetDir}`);
|
|
23906
24023
|
}
|
|
23907
24024
|
);
|
|
23908
24025
|
}
|