carrick 0.3.57 → 0.3.59
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 +117 -26
- package/bin/carrick.mjs +13 -2
- package/dist/auth/credentials.d.ts +14 -0
- package/dist/auth/credentials.js +86 -0
- package/dist/auth/credentials.js.map +1 -0
- package/dist/auth/oauth.d.ts +11 -0
- package/dist/auth/oauth.js +119 -0
- package/dist/auth/oauth.js.map +1 -0
- package/dist/auth/read.d.ts +139 -0
- package/dist/auth/read.js +44 -0
- package/dist/auth/read.js.map +1 -0
- package/dist/auth/run.d.ts +12 -0
- package/dist/auth/run.js +68 -0
- package/dist/auth/run.js.map +1 -0
- package/dist/contract.d.ts +10 -0
- package/dist/contract.js +3 -0
- package/dist/contract.js.map +1 -1
- package/dist/definition.d.ts +33 -0
- package/dist/definition.js +107 -0
- package/dist/definition.js.map +1 -0
- package/dist/diagnostics.d.ts +72 -3
- package/dist/diagnostics.js +275 -55
- package/dist/diagnostics.js.map +1 -1
- package/dist/hook/refresh.d.ts +32 -0
- package/dist/hook/refresh.js +138 -0
- package/dist/hook/refresh.js.map +1 -0
- package/dist/hook/session-start.js +13 -0
- package/dist/hook/session-start.js.map +1 -1
- package/dist/init/connect.d.ts +17 -0
- package/dist/init/connect.js +120 -0
- package/dist/init/connect.js.map +1 -0
- package/dist/init/mcp.d.ts +50 -0
- package/dist/init/mcp.js +235 -0
- package/dist/init/mcp.js.map +1 -0
- package/dist/init/projects.d.ts +46 -0
- package/dist/init/projects.js +137 -0
- package/dist/init/projects.js.map +1 -0
- package/dist/init/repos.d.ts +113 -19
- package/dist/init/repos.js +60 -39
- package/dist/init/repos.js.map +1 -1
- package/dist/init/run.d.ts +16 -0
- package/dist/init/run.js +243 -61
- package/dist/init/run.js.map +1 -1
- package/dist/init/settings.d.ts +1 -1
- package/dist/init/settings.js +1 -1
- package/dist/init/settings.js.map +1 -1
- package/dist/lens.d.ts +41 -0
- package/dist/lens.js +116 -0
- package/dist/lens.js.map +1 -0
- package/dist/server.js +327 -24
- package/dist/server.js.map +1 -1
- package/dist/surfaces.d.ts +28 -0
- package/dist/surfaces.js +70 -0
- package/dist/surfaces.js.map +1 -0
- package/package.json +6 -6
- package/sidecar/dist/src/capture/deno-project.d.ts +41 -0
- package/sidecar/dist/src/capture/deno-project.js +513 -0
- package/sidecar/dist/src/capture/index.d.ts +1 -0
- package/sidecar/dist/src/capture/index.js +60 -19
- package/sidecar/dist/src/capture/self-check.d.ts +2 -0
- package/sidecar/dist/src/capture/self-check.js +3 -2
- package/sidecar/dist/src/project-loader.js +22 -1
- package/dist/init/identity.d.ts +0 -20
- package/dist/init/identity.js +0 -60
- package/dist/init/identity.js.map +0 -1
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
// Listing and creating Carrick projects from the terminal (carrick#955).
|
|
2
|
+
//
|
|
3
|
+
// `carrick init --project <slug>` could only ever point at a browser: the
|
|
4
|
+
// workspace read (`resolve-repos`) returns the projects the named repos are
|
|
5
|
+
// already in, never the workspace's project list, and creation lived only in
|
|
6
|
+
// the dashboard. These two actions are the terminal half.
|
|
7
|
+
//
|
|
8
|
+
// **The server may not have them.** They are a separate cloud change, so
|
|
9
|
+
// every call here is a probe: a workspace whose API does not answer them gets
|
|
10
|
+
// today's browser links and the same wait, and the release does not depend on
|
|
11
|
+
// a deploy. "Absent" is deliberately wide, because it is not one status code:
|
|
12
|
+
// an API that has never heard of an action answers a credential-kind gate
|
|
13
|
+
// first (403 today, since the CLI credential is an MCP-scoped key and the
|
|
14
|
+
// action is not on that key's read list), and a later one may answer 404. The
|
|
15
|
+
// only status treated as fatal is 401, because the credential was already
|
|
16
|
+
// proven by the workspace read that runs before this — a rejection here is a
|
|
17
|
+
// real one and must not read as a missing feature.
|
|
18
|
+
//
|
|
19
|
+
// A refusal is separated from an absence by the pair (status, body): a 400 or
|
|
20
|
+
// a 409 carrying an `error` string is the server stating why a create cannot
|
|
21
|
+
// happen (slug taken, reserved, rate limited), and that sentence is the
|
|
22
|
+
// user's to read. Everything else is an absence.
|
|
23
|
+
import { z } from "zod";
|
|
24
|
+
import { API_BASE } from "../auth/credentials.js";
|
|
25
|
+
const project = z.object({
|
|
26
|
+
slug: z.string(),
|
|
27
|
+
name: z.string(),
|
|
28
|
+
archived: z.boolean(),
|
|
29
|
+
repo_count: z.number().int().nonnegative().nullable(),
|
|
30
|
+
});
|
|
31
|
+
const listResponse = z.object({
|
|
32
|
+
schema: z.literal("carrick.list-projects/0"),
|
|
33
|
+
projects: z.array(project),
|
|
34
|
+
});
|
|
35
|
+
const createResponse = z.object({
|
|
36
|
+
schema: z.literal("carrick.create-project/0"),
|
|
37
|
+
project,
|
|
38
|
+
});
|
|
39
|
+
const REJECTED = "Carrick rejected this credential. Run carrick login (unset CARRICK_TOKEN first if it overrides your login).";
|
|
40
|
+
async function post(token, body, request, signal) {
|
|
41
|
+
try {
|
|
42
|
+
return await request(`${API_BASE}/types/check-or-upload`, {
|
|
43
|
+
method: "POST",
|
|
44
|
+
redirect: "error",
|
|
45
|
+
signal: AbortSignal.any([AbortSignal.timeout(30_000), ...(signal ? [signal] : [])]),
|
|
46
|
+
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
|
|
47
|
+
body: JSON.stringify(body),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
// A request that never reached the server says nothing about whether the
|
|
52
|
+
// action exists, and the workspace read that precedes this one already
|
|
53
|
+
// reports an unreachable API. Fall back rather than fail the run.
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/** The `error` sentence a refusal carries, when it carries one. */
|
|
58
|
+
async function refusal(result) {
|
|
59
|
+
if (result.status !== 400 && result.status !== 409)
|
|
60
|
+
return null;
|
|
61
|
+
try {
|
|
62
|
+
const payload = await result.json();
|
|
63
|
+
const message = payload?.error;
|
|
64
|
+
return typeof message === "string" && message.trim() !== "" ? message : null;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Every project in the signed-in workspace, or null when this API has no such
|
|
72
|
+
* action. Throws only on 401.
|
|
73
|
+
*/
|
|
74
|
+
export async function listProjects(token, request = fetch, signal) {
|
|
75
|
+
const result = await post(token, { action: "list-projects" }, request, signal);
|
|
76
|
+
if (!result)
|
|
77
|
+
return null;
|
|
78
|
+
if (result.status === 401)
|
|
79
|
+
throw new Error(REJECTED);
|
|
80
|
+
if (!result.ok)
|
|
81
|
+
return null;
|
|
82
|
+
let payload;
|
|
83
|
+
try {
|
|
84
|
+
payload = await result.json();
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
const parsed = listResponse.safeParse(payload);
|
|
90
|
+
// The schema tag is the handshake. An API that answers this action with
|
|
91
|
+
// some other shape is one this client cannot read, which is the same
|
|
92
|
+
// situation as not having it.
|
|
93
|
+
return parsed.success ? parsed.data.projects : null;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Create one project in the signed-in workspace.
|
|
97
|
+
*
|
|
98
|
+
* The slug is sent as given: `carrick init` validates it against the same
|
|
99
|
+
* shape the dashboard enforces before it ever reaches here, so a slug this
|
|
100
|
+
* client sends is one the server can accept or refuse on its own rules, never
|
|
101
|
+
* one it has to normalise silently into something the user did not ask for.
|
|
102
|
+
*/
|
|
103
|
+
export async function createProject(token, slug, name = slug, request = fetch, signal) {
|
|
104
|
+
const result = await post(token, { action: "create-project", slug, name }, request, signal);
|
|
105
|
+
if (!result)
|
|
106
|
+
return { kind: "absent" };
|
|
107
|
+
if (result.status === 401)
|
|
108
|
+
throw new Error(REJECTED);
|
|
109
|
+
if (!result.ok) {
|
|
110
|
+
const message = await refusal(result);
|
|
111
|
+
return message ? { kind: "refused", message } : { kind: "absent" };
|
|
112
|
+
}
|
|
113
|
+
let payload;
|
|
114
|
+
try {
|
|
115
|
+
payload = await result.json();
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
return { kind: "absent" };
|
|
119
|
+
}
|
|
120
|
+
const parsed = createResponse.safeParse(payload);
|
|
121
|
+
return parsed.success ? { kind: "created", project: parsed.data.project } : { kind: "absent" };
|
|
122
|
+
}
|
|
123
|
+
/** The list as init prints it: one line per project, active ones first. */
|
|
124
|
+
export function projectLines(projects) {
|
|
125
|
+
const ordered = [...projects].sort((left, right) => left.archived === right.archived
|
|
126
|
+
? left.slug.localeCompare(right.slug)
|
|
127
|
+
: Number(left.archived) - Number(right.archived));
|
|
128
|
+
return ordered.map((entry) => {
|
|
129
|
+
const repos = entry.repo_count === null
|
|
130
|
+
? ""
|
|
131
|
+
: ` ${entry.repo_count} repo${entry.repo_count === 1 ? "" : "s"}`;
|
|
132
|
+
const archived = entry.archived ? " (archived)" : "";
|
|
133
|
+
const named = entry.name === entry.slug ? "" : ` ${entry.name}`;
|
|
134
|
+
return ` ${entry.slug}${named}${repos}${archived}`;
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=projects.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projects.js","sourceRoot":"","sources":["../../src/init/projects.ts"],"names":[],"mappings":"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"}
|
package/dist/init/repos.d.ts
CHANGED
|
@@ -1,19 +1,113 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
declare const proposal: z.ZodObject<{
|
|
3
|
+
schema: z.ZodLiteral<"carrick.derive/0">;
|
|
4
|
+
workspace: z.ZodString;
|
|
5
|
+
repos_detected_by: z.ZodString;
|
|
6
|
+
repos_added: z.ZodArray<z.ZodString, "many">;
|
|
7
|
+
repos_excluded: z.ZodArray<z.ZodString, "many">;
|
|
8
|
+
missing: z.ZodArray<z.ZodString, "many">;
|
|
9
|
+
parent_proposal: z.ZodNullable<z.ZodObject<{
|
|
10
|
+
directory: z.ZodString;
|
|
11
|
+
repos: z.ZodArray<z.ZodString, "many">;
|
|
12
|
+
}, "strip", z.ZodTypeAny, {
|
|
13
|
+
repos: string[];
|
|
14
|
+
directory: string;
|
|
15
|
+
}, {
|
|
16
|
+
repos: string[];
|
|
17
|
+
directory: string;
|
|
18
|
+
}>>;
|
|
19
|
+
repos: z.ZodArray<z.ZodObject<{
|
|
20
|
+
path: z.ZodString;
|
|
21
|
+
reason: z.ZodString;
|
|
22
|
+
services: z.ZodArray<z.ZodObject<{
|
|
23
|
+
serviceName: z.ZodNullable<z.ZodString>;
|
|
24
|
+
directory: z.ZodOptional<z.ZodString>;
|
|
25
|
+
tsconfig: z.ZodOptional<z.ZodString>;
|
|
26
|
+
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
27
|
+
serviceName: z.ZodNullable<z.ZodString>;
|
|
28
|
+
directory: z.ZodOptional<z.ZodString>;
|
|
29
|
+
tsconfig: z.ZodOptional<z.ZodString>;
|
|
30
|
+
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
31
|
+
serviceName: z.ZodNullable<z.ZodString>;
|
|
32
|
+
directory: z.ZodOptional<z.ZodString>;
|
|
33
|
+
tsconfig: z.ZodOptional<z.ZodString>;
|
|
34
|
+
}, z.ZodTypeAny, "passthrough">>, "many">;
|
|
35
|
+
config: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
36
|
+
warnings: z.ZodArray<z.ZodString, "many">;
|
|
37
|
+
}, "strip", z.ZodTypeAny, {
|
|
38
|
+
services: z.objectOutputType<{
|
|
39
|
+
serviceName: z.ZodNullable<z.ZodString>;
|
|
40
|
+
directory: z.ZodOptional<z.ZodString>;
|
|
41
|
+
tsconfig: z.ZodOptional<z.ZodString>;
|
|
42
|
+
}, z.ZodTypeAny, "passthrough">[];
|
|
43
|
+
path: string;
|
|
44
|
+
reason: string;
|
|
45
|
+
config: Record<string, unknown> | null;
|
|
46
|
+
warnings: string[];
|
|
47
|
+
}, {
|
|
48
|
+
services: z.objectInputType<{
|
|
49
|
+
serviceName: z.ZodNullable<z.ZodString>;
|
|
50
|
+
directory: z.ZodOptional<z.ZodString>;
|
|
51
|
+
tsconfig: z.ZodOptional<z.ZodString>;
|
|
52
|
+
}, z.ZodTypeAny, "passthrough">[];
|
|
53
|
+
path: string;
|
|
54
|
+
reason: string;
|
|
55
|
+
config: Record<string, unknown> | null;
|
|
56
|
+
warnings: string[];
|
|
57
|
+
}>, "many">;
|
|
58
|
+
}, "strip", z.ZodTypeAny, {
|
|
59
|
+
schema: "carrick.derive/0";
|
|
60
|
+
workspace: string;
|
|
61
|
+
repos: {
|
|
62
|
+
services: z.objectOutputType<{
|
|
63
|
+
serviceName: z.ZodNullable<z.ZodString>;
|
|
64
|
+
directory: z.ZodOptional<z.ZodString>;
|
|
65
|
+
tsconfig: z.ZodOptional<z.ZodString>;
|
|
66
|
+
}, z.ZodTypeAny, "passthrough">[];
|
|
67
|
+
path: string;
|
|
68
|
+
reason: string;
|
|
69
|
+
config: Record<string, unknown> | null;
|
|
70
|
+
warnings: string[];
|
|
71
|
+
}[];
|
|
72
|
+
repos_detected_by: string;
|
|
73
|
+
repos_added: string[];
|
|
74
|
+
repos_excluded: string[];
|
|
75
|
+
missing: string[];
|
|
76
|
+
parent_proposal: {
|
|
77
|
+
repos: string[];
|
|
78
|
+
directory: string;
|
|
79
|
+
} | null;
|
|
80
|
+
}, {
|
|
81
|
+
schema: "carrick.derive/0";
|
|
82
|
+
workspace: string;
|
|
83
|
+
repos: {
|
|
84
|
+
services: z.objectInputType<{
|
|
85
|
+
serviceName: z.ZodNullable<z.ZodString>;
|
|
86
|
+
directory: z.ZodOptional<z.ZodString>;
|
|
87
|
+
tsconfig: z.ZodOptional<z.ZodString>;
|
|
88
|
+
}, z.ZodTypeAny, "passthrough">[];
|
|
89
|
+
path: string;
|
|
90
|
+
reason: string;
|
|
91
|
+
config: Record<string, unknown> | null;
|
|
92
|
+
warnings: string[];
|
|
93
|
+
}[];
|
|
94
|
+
repos_detected_by: string;
|
|
95
|
+
repos_added: string[];
|
|
96
|
+
repos_excluded: string[];
|
|
97
|
+
missing: string[];
|
|
98
|
+
parent_proposal: {
|
|
99
|
+
repos: string[];
|
|
100
|
+
directory: string;
|
|
101
|
+
} | null;
|
|
102
|
+
}>;
|
|
103
|
+
export type WorkspaceProposal = z.infer<typeof proposal>;
|
|
104
|
+
/** Rust owns service selection, tsconfig precedence and configuration validation. */
|
|
105
|
+
export declare function deriveWorkspace(workspace: string): WorkspaceProposal;
|
|
106
|
+
/** An explicit init may create a missing file once, including under a race. */
|
|
107
|
+
export declare function writeConfigs(plan: WorkspaceProposal): Array<{
|
|
108
|
+
path: string;
|
|
109
|
+
created: boolean;
|
|
110
|
+
}>;
|
|
111
|
+
/** Only GitHub origin identities are sent to the workspace metadata read. */
|
|
112
|
+
export declare function githubRemote(repo: string): string | null;
|
|
113
|
+
export {};
|
package/dist/init/repos.js
CHANGED
|
@@ -1,46 +1,67 @@
|
|
|
1
|
-
// Which directories in this folder are repos to index.
|
|
2
|
-
//
|
|
3
|
-
// A proposal, not a decision: the list goes into `carrick-workspace.json`,
|
|
4
|
-
// which the scanner reads literally and a user can edit. There is no walk
|
|
5
|
-
// deeper than one level and no search order to reason about (E20) — a repo is
|
|
6
|
-
// a directory here with a `package.json` in it.
|
|
7
1
|
import fs from "node:fs";
|
|
8
2
|
import path from "node:path";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
3
|
+
import { spawnSync } from "node:child_process";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { nativeEnv, resolveNativeBinary } from "../native.js";
|
|
6
|
+
const service = z.object({ serviceName: z.string().nullable(), directory: z.string().optional(), tsconfig: z.string().optional() }).passthrough();
|
|
7
|
+
const proposal = z.object({
|
|
8
|
+
schema: z.literal("carrick.derive/0"), workspace: z.string(), repos_detected_by: z.string(),
|
|
9
|
+
repos_added: z.array(z.string()), repos_excluded: z.array(z.string()), missing: z.array(z.string()),
|
|
10
|
+
parent_proposal: z.object({ directory: z.string(), repos: z.array(z.string()) }).nullable(),
|
|
11
|
+
repos: z.array(z.object({ path: z.string(), reason: z.string(), services: z.array(service), config: z.record(z.unknown()).nullable(), warnings: z.array(z.string()) })),
|
|
12
|
+
});
|
|
13
|
+
/** Rust owns service selection, tsconfig precedence and configuration validation. */
|
|
14
|
+
export function deriveWorkspace(workspace) {
|
|
15
|
+
const native = resolveNativeBinary();
|
|
16
|
+
if (!native.binary)
|
|
17
|
+
throw new Error(native.problem ?? "The Carrick scanner is not installed.");
|
|
18
|
+
const result = spawnSync(native.binary, ["derive", "--workspace", workspace, "--json"], {
|
|
19
|
+
encoding: "utf8", env: nativeEnv(), timeout: 30_000, maxBuffer: 8 * 1024 * 1024,
|
|
20
|
+
});
|
|
21
|
+
if (result.error)
|
|
22
|
+
throw new Error(`Could not derive the workspace: ${result.error.message}`);
|
|
23
|
+
if (result.status !== 0)
|
|
24
|
+
throw new Error(result.stderr.trim() || "The scanner could not derive the workspace.");
|
|
25
|
+
const parsed = proposal.safeParse(JSON.parse(result.stdout));
|
|
26
|
+
if (!parsed.success)
|
|
27
|
+
throw new Error("The scanner returned an unsupported workspace proposal. Install matching Carrick CLI and scanner versions.");
|
|
28
|
+
return parsed.data;
|
|
25
29
|
}
|
|
26
|
-
/**
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
/** An explicit init may create a missing file once, including under a race. */
|
|
31
|
+
export function writeConfigs(plan) {
|
|
32
|
+
return plan.repos.map((repo) => {
|
|
33
|
+
const target = path.join(repo.path, "carrick.json");
|
|
34
|
+
if (repo.config === null)
|
|
35
|
+
return { path: target, created: false };
|
|
36
|
+
try {
|
|
37
|
+
fs.writeFileSync(target, `${JSON.stringify(repo.config, null, 2)}\n`, { flag: "wx" });
|
|
38
|
+
return { path: target, created: true };
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
if (error.code === "EEXIST")
|
|
42
|
+
return { path: target, created: false };
|
|
43
|
+
throw error;
|
|
38
44
|
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/** Only GitHub origin identities are sent to the workspace metadata read. */
|
|
48
|
+
export function githubRemote(repo) {
|
|
49
|
+
const result = spawnSync("git", ["-C", repo, "remote", "get-url", "origin"], { encoding: "utf8", timeout: 5000 });
|
|
50
|
+
if (result.status !== 0)
|
|
51
|
+
return null;
|
|
52
|
+
const remote = result.stdout.trim();
|
|
53
|
+
const scp = /^git@github\.com:([A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+?)(?:\.git)?$/.exec(remote);
|
|
54
|
+
if (scp)
|
|
55
|
+
return scp[1];
|
|
56
|
+
try {
|
|
57
|
+
const url = new URL(remote);
|
|
58
|
+
if (url.hostname.toLowerCase() !== "github.com" || !["https:", "ssh:"].includes(url.protocol))
|
|
59
|
+
return null;
|
|
60
|
+
const name = url.pathname.replace(/^\//, "").replace(/\.git$/, "");
|
|
61
|
+
return /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(name) ? name : null;
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return null;
|
|
39
65
|
}
|
|
40
|
-
const normal = (entry) => entry.replace(/^\.\//, "").replace(/\/$/, "");
|
|
41
|
-
const known = new Set(listed.map(normal));
|
|
42
|
-
const added = found.filter((entry) => !known.has(normal(entry)));
|
|
43
|
-
const repos = [...listed, ...added];
|
|
44
|
-
return { body: `${JSON.stringify({ repos }, null, 2)}\n`, repos, added };
|
|
45
66
|
}
|
|
46
67
|
//# sourceMappingURL=repos.js.map
|
package/dist/init/repos.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repos.js","sourceRoot":"","sources":["../../src/init/repos.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"repos.js","sourceRoot":"","sources":["../../src/init/repos.ts"],"names":[],"mappings":"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"}
|
package/dist/init/run.d.ts
CHANGED
|
@@ -1,11 +1,27 @@
|
|
|
1
1
|
export type InitOptions = {
|
|
2
2
|
workspace: string;
|
|
3
|
+
/** Require every proposed GitHub repo to belong to this project. */
|
|
4
|
+
project: string | null;
|
|
3
5
|
/** Answer yes to the repo list rather than asking. */
|
|
4
6
|
assumeYes: boolean;
|
|
5
7
|
/** Write the files, print the lines, and do not build the index. */
|
|
6
8
|
skipIndex: boolean;
|
|
7
9
|
};
|
|
8
10
|
export declare function parseArgs(argv: string[], cwd?: string): InitOptions | string;
|
|
11
|
+
/**
|
|
12
|
+
* The editor lines, one line per editor that is on the machine.
|
|
13
|
+
*
|
|
14
|
+
* `--install-extension <id>` resolves the id against that editor's own gallery,
|
|
15
|
+
* and the three editors below read three different ones: VS Code the VS Code
|
|
16
|
+
* Marketplace, Cursor and Windsurf each their own. The extension is published
|
|
17
|
+
* to all three, so the id is a command every one of them can run
|
|
18
|
+
* (carrick#915). Any other editor gets the server's command and no claim about
|
|
19
|
+
* the editor: the per-editor results table in `plugin/TEST-PLAN.md` section 6
|
|
20
|
+
* is still empty.
|
|
21
|
+
*
|
|
22
|
+
* `onPath` is injected so a test can state each machine.
|
|
23
|
+
*/
|
|
24
|
+
export declare function editorLines(onPath: (command: string) => boolean): string[];
|
|
9
25
|
export declare function init(argv: string[]): Promise<number>;
|
|
10
26
|
/** `carrick templates <name>`, so the workflow above is one command. */
|
|
11
27
|
export declare function templates(argv: string[]): number;
|