contentrain 0.3.4 → 0.4.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/README.md +9 -1
- package/dist/{activity-CtOcAA4X.mjs → activity-DMQsYlzz.mjs} +2 -2
- package/dist/{branches-C_kgqSv9.mjs → branches-D330IxDO.mjs} +2 -2
- package/dist/{cdn-build-CDv_yM15.mjs → cdn-build-D_d3p4OZ.mjs} +2 -2
- package/dist/{cdn-init-DXQ-3V_c.mjs → cdn-init-Bhnil0F8.mjs} +2 -2
- package/dist/{client-D4xW8aLz.mjs → client-CLV4XoJz.mjs} +18 -0
- package/dist/connect-DiSYnxFd.mjs +252 -0
- package/dist/{diff-Cq6iSnaD.mjs → diff--halNUpG.mjs} +1 -0
- package/dist/{generate-DDEDRLdy.mjs → generate-DrUojrk8.mjs} +1 -0
- package/dist/index.mjs +6 -6
- package/dist/{init-BARgfYUV.mjs → init-Q9B0iYtu.mjs} +3 -0
- package/dist/login-wRBvHDCi.mjs +125 -0
- package/dist/{logout-CRM4fCSH.mjs → logout-xPTGu6vx.mjs} +1 -1
- package/dist/{login-CO0hxICh.mjs → oauth-server-1p6y1H30.mjs} +15 -133
- package/dist/{resolve-context-BMV7JwCw.mjs → resolve-context-BwcikcF0.mjs} +1 -1
- package/dist/{status-Bi9HYgcA.mjs → status-BmQZGdZX.mjs} +1 -0
- package/dist/{status-ts5FvDEZ.mjs → status-UvjbO4eS.mjs} +2 -2
- package/dist/studio-B8lF0fQx.mjs +24 -0
- package/dist/{submissions-6_OCrUNF.mjs → submissions-Dw0ChFDi.mjs} +2 -2
- package/dist/{usage-BAb4q7Pz.mjs → usage-BqriRRqE.mjs} +2 -2
- package/dist/{webhooks-C39IItU1.mjs → webhooks-B1OhcCtZ.mjs} +2 -2
- package/dist/{whoami-D8NyFKs_.mjs → whoami-CWvTYzum.mjs} +1 -1
- package/package.json +1 -1
- package/dist/studio-BmXS_bCq.mjs +0 -23
package/README.md
CHANGED
|
@@ -58,6 +58,7 @@ Requirements:
|
|
|
58
58
|
| `contentrain generate` | Generate `.contentrain/client/` and `#contentrain` package imports |
|
|
59
59
|
| `contentrain diff` | Review and merge or reject pending `contentrain/*` branches |
|
|
60
60
|
| `contentrain serve` | Start the local review UI or the MCP stdio server |
|
|
61
|
+
| `contentrain studio connect` | Connect a repository to a Studio project |
|
|
61
62
|
| `contentrain studio login` | Authenticate with Contentrain Studio |
|
|
62
63
|
| `contentrain studio logout` | Log out from Studio |
|
|
63
64
|
| `contentrain studio whoami` | Show current authentication status |
|
|
@@ -172,11 +173,18 @@ to understand:
|
|
|
172
173
|
|
|
173
174
|
The `studio` command group connects the CLI to [Contentrain Studio](https://studio.contentrain.io) for enterprise workflows.
|
|
174
175
|
|
|
175
|
-
Authenticate:
|
|
176
|
+
Authenticate and connect:
|
|
176
177
|
|
|
177
178
|
```bash
|
|
178
179
|
contentrain studio login
|
|
179
180
|
contentrain studio whoami
|
|
181
|
+
contentrain studio connect
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
The `connect` command links your local repository to a Studio project. It detects the git remote, verifies GitHub App installation, scans for `.contentrain/` configuration, and creates the project — all in one interactive flow.
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
contentrain studio connect --workspace ws-123
|
|
180
188
|
```
|
|
181
189
|
|
|
182
190
|
Set up CDN for content delivery:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { i as pc } from "./ui-B5mXontH.mjs";
|
|
2
|
-
import { n as resolveStudioClient } from "./client-
|
|
3
|
-
import { t as resolveStudioContext } from "./resolve-context-
|
|
2
|
+
import { n as resolveStudioClient } from "./client-CLV4XoJz.mjs";
|
|
3
|
+
import { t as resolveStudioContext } from "./resolve-context-BwcikcF0.mjs";
|
|
4
4
|
import { defineCommand } from "citty";
|
|
5
5
|
import { intro, log, outro, spinner } from "@clack/prompts";
|
|
6
6
|
//#region src/studio/commands/activity.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { i as pc, r as formatTable, t as formatCount } from "./ui-B5mXontH.mjs";
|
|
2
|
-
import { n as resolveStudioClient } from "./client-
|
|
3
|
-
import { t as resolveStudioContext } from "./resolve-context-
|
|
2
|
+
import { n as resolveStudioClient } from "./client-CLV4XoJz.mjs";
|
|
3
|
+
import { t as resolveStudioContext } from "./resolve-context-BwcikcF0.mjs";
|
|
4
4
|
import { defineCommand } from "citty";
|
|
5
5
|
import { confirm, intro, isCancel, log, outro, select, spinner } from "@clack/prompts";
|
|
6
6
|
//#region src/studio/commands/branches.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { i as pc, t as formatCount } from "./ui-B5mXontH.mjs";
|
|
2
|
-
import { n as resolveStudioClient } from "./client-
|
|
3
|
-
import { t as resolveStudioContext } from "./resolve-context-
|
|
2
|
+
import { n as resolveStudioClient } from "./client-CLV4XoJz.mjs";
|
|
3
|
+
import { t as resolveStudioContext } from "./resolve-context-BwcikcF0.mjs";
|
|
4
4
|
import { defineCommand } from "citty";
|
|
5
5
|
import { intro, log, outro, spinner } from "@clack/prompts";
|
|
6
6
|
//#region src/studio/commands/cdn-build.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { i as pc } from "./ui-B5mXontH.mjs";
|
|
2
|
-
import { n as resolveStudioClient } from "./client-
|
|
3
|
-
import { t as resolveStudioContext } from "./resolve-context-
|
|
2
|
+
import { n as resolveStudioClient } from "./client-CLV4XoJz.mjs";
|
|
3
|
+
import { t as resolveStudioContext } from "./resolve-context-BwcikcF0.mjs";
|
|
4
4
|
import { defineCommand } from "citty";
|
|
5
5
|
import { confirm, intro, isCancel, log, outro, spinner } from "@clack/prompts";
|
|
6
6
|
//#region src/studio/commands/cdn-init.ts
|
|
@@ -213,6 +213,24 @@ var StudioApiClient = class {
|
|
|
213
213
|
async listProjects(workspaceId) {
|
|
214
214
|
return this.request("GET", `/api/workspaces/${workspaceId}/projects`);
|
|
215
215
|
}
|
|
216
|
+
async createProject(workspaceId, payload) {
|
|
217
|
+
return this.request("POST", `/api/workspaces/${workspaceId}/projects`, { body: payload });
|
|
218
|
+
}
|
|
219
|
+
async listGitHubInstallations() {
|
|
220
|
+
return this.request("GET", "/api/github/installations");
|
|
221
|
+
}
|
|
222
|
+
async getGitHubSetupUrl() {
|
|
223
|
+
return this.request("GET", "/api/github/setup");
|
|
224
|
+
}
|
|
225
|
+
async listGitHubRepos(installationId) {
|
|
226
|
+
return this.request("GET", "/api/github/repos", { query: { installationId: String(installationId) } });
|
|
227
|
+
}
|
|
228
|
+
async scanRepository(installationId, repoFullName) {
|
|
229
|
+
return this.request("GET", "/api/github/scan", { query: {
|
|
230
|
+
installationId: String(installationId),
|
|
231
|
+
repo: repoFullName
|
|
232
|
+
} });
|
|
233
|
+
}
|
|
216
234
|
async listBranches(wid, pid) {
|
|
217
235
|
return this.request("GET", `/api/workspaces/${wid}/projects/${pid}/branches`);
|
|
218
236
|
}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { i as pc } from "./ui-B5mXontH.mjs";
|
|
2
|
+
import { c as saveDefaults, n as resolveStudioClient } from "./client-CLV4XoJz.mjs";
|
|
3
|
+
import { n as openBrowser, t as startOAuthServer } from "./oauth-server-1p6y1H30.mjs";
|
|
4
|
+
import { defineCommand } from "citty";
|
|
5
|
+
import { confirm, intro, isCancel, log, outro, select, spinner, text } from "@clack/prompts";
|
|
6
|
+
import { simpleGit } from "simple-git";
|
|
7
|
+
//#region src/studio/commands/connect.ts
|
|
8
|
+
var connect_default = defineCommand({
|
|
9
|
+
meta: {
|
|
10
|
+
name: "connect",
|
|
11
|
+
description: "Connect this repository to a Contentrain Studio project"
|
|
12
|
+
},
|
|
13
|
+
args: {
|
|
14
|
+
workspace: {
|
|
15
|
+
type: "string",
|
|
16
|
+
description: "Workspace ID",
|
|
17
|
+
required: false
|
|
18
|
+
},
|
|
19
|
+
json: {
|
|
20
|
+
type: "boolean",
|
|
21
|
+
description: "JSON output",
|
|
22
|
+
required: false
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
async run({ args }) {
|
|
26
|
+
if (!args.json) intro(pc.bold("contentrain studio connect"));
|
|
27
|
+
try {
|
|
28
|
+
const client = await resolveStudioClient();
|
|
29
|
+
const s1 = args.json ? null : spinner();
|
|
30
|
+
s1?.start("Loading workspaces...");
|
|
31
|
+
const workspaces = await client.listWorkspaces();
|
|
32
|
+
s1?.stop(`${workspaces.length} workspace(s) found`);
|
|
33
|
+
if (workspaces.length === 0) {
|
|
34
|
+
log.warning("No workspaces found. Create one at studio.contentrain.io first.");
|
|
35
|
+
outro("");
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
let workspaceId = args.workspace;
|
|
39
|
+
if (!workspaceId) if (workspaces.length === 1) {
|
|
40
|
+
workspaceId = workspaces[0].id;
|
|
41
|
+
if (!args.json) log.info(`Using workspace: ${pc.cyan(workspaces[0].name)}`);
|
|
42
|
+
} else {
|
|
43
|
+
const choice = await select({
|
|
44
|
+
message: "Select workspace",
|
|
45
|
+
options: workspaces.map((w) => ({
|
|
46
|
+
value: w.id,
|
|
47
|
+
label: w.name,
|
|
48
|
+
hint: w.plan
|
|
49
|
+
}))
|
|
50
|
+
});
|
|
51
|
+
if (isCancel(choice)) {
|
|
52
|
+
outro(pc.dim("Cancelled"));
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
workspaceId = choice;
|
|
56
|
+
}
|
|
57
|
+
const workspace = workspaces.find((w) => w.id === workspaceId);
|
|
58
|
+
const s2 = args.json ? null : spinner();
|
|
59
|
+
s2?.start("Checking GitHub App installation...");
|
|
60
|
+
let installations = await client.listGitHubInstallations();
|
|
61
|
+
s2?.stop(installations.length > 0 ? `${installations.length} GitHub installation(s) found` : "No GitHub App installed");
|
|
62
|
+
if (installations.length === 0) {
|
|
63
|
+
const shouldInstall = await confirm({ message: "The Contentrain GitHub App is required. Install it now?" });
|
|
64
|
+
if (isCancel(shouldInstall) || !shouldInstall) {
|
|
65
|
+
outro(pc.dim("Cancelled"));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const setupData = await client.getGitHubSetupUrl();
|
|
69
|
+
const oauth = await startOAuthServer();
|
|
70
|
+
const installUrl = `${setupData.url}&redirect_uri=${encodeURIComponent(oauth.callbackUrl)}&state=${oauth.state}`;
|
|
71
|
+
if (!args.json) log.info(`If the browser doesn't open, visit:\n ${pc.cyan(installUrl)}`);
|
|
72
|
+
await openBrowser(installUrl);
|
|
73
|
+
const s2b = args.json ? null : spinner();
|
|
74
|
+
s2b?.start("Waiting for GitHub App installation...");
|
|
75
|
+
try {
|
|
76
|
+
if ((await oauth.waitForCallback()).state !== oauth.state) {
|
|
77
|
+
s2b?.stop("Failed");
|
|
78
|
+
log.error("State mismatch. Please try again.");
|
|
79
|
+
process.exitCode = 1;
|
|
80
|
+
outro("");
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
s2b?.stop("GitHub App installed");
|
|
84
|
+
} catch (error) {
|
|
85
|
+
s2b?.stop("Failed");
|
|
86
|
+
oauth.close();
|
|
87
|
+
log.error(error instanceof Error ? error.message : String(error));
|
|
88
|
+
process.exitCode = 1;
|
|
89
|
+
outro("");
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
installations = await client.listGitHubInstallations();
|
|
93
|
+
if (installations.length === 0) {
|
|
94
|
+
log.error("GitHub App installation not detected. Please try again.");
|
|
95
|
+
process.exitCode = 1;
|
|
96
|
+
outro("");
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
let installation;
|
|
101
|
+
if (installations.length === 1) {
|
|
102
|
+
installation = installations[0];
|
|
103
|
+
if (!args.json) log.info(`Using GitHub account: ${pc.cyan(installation.accountLogin)}`);
|
|
104
|
+
} else {
|
|
105
|
+
const choice = await select({
|
|
106
|
+
message: "Select GitHub account",
|
|
107
|
+
options: installations.map((inst) => ({
|
|
108
|
+
value: String(inst.id),
|
|
109
|
+
label: inst.accountLogin,
|
|
110
|
+
hint: inst.accountType
|
|
111
|
+
}))
|
|
112
|
+
});
|
|
113
|
+
if (isCancel(choice)) {
|
|
114
|
+
outro(pc.dim("Cancelled"));
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
installation = installations.find((i) => String(i.id) === choice);
|
|
118
|
+
}
|
|
119
|
+
const s3 = args.json ? null : spinner();
|
|
120
|
+
s3?.start("Detecting git remote...");
|
|
121
|
+
let detectedRepoFullName = null;
|
|
122
|
+
try {
|
|
123
|
+
const origin = (await simpleGit(process.cwd()).getRemotes(true)).find((r) => r.name === "origin");
|
|
124
|
+
if (origin?.refs?.fetch) detectedRepoFullName = parseGitHubRepoFromUrl(origin.refs.fetch);
|
|
125
|
+
} catch {}
|
|
126
|
+
const repos = await client.listGitHubRepos(installation.id);
|
|
127
|
+
s3?.stop(detectedRepoFullName ? `Detected: ${pc.cyan(detectedRepoFullName)}` : `${repos.length} accessible repo(s)`);
|
|
128
|
+
let selectedRepo = null;
|
|
129
|
+
if (detectedRepoFullName) {
|
|
130
|
+
const match = repos.find((r) => r.fullName === detectedRepoFullName);
|
|
131
|
+
if (match) {
|
|
132
|
+
const useDetected = await confirm({ message: `Connect to ${pc.cyan(match.fullName)}?` });
|
|
133
|
+
if (isCancel(useDetected)) {
|
|
134
|
+
outro(pc.dim("Cancelled"));
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
selectedRepo = useDetected ? match : await pickRepo(repos);
|
|
138
|
+
} else {
|
|
139
|
+
if (!args.json) log.warning(`Detected remote "${detectedRepoFullName}" is not accessible to the GitHub App.`);
|
|
140
|
+
selectedRepo = await pickRepo(repos);
|
|
141
|
+
}
|
|
142
|
+
} else {
|
|
143
|
+
if (repos.length === 0) {
|
|
144
|
+
log.error("No repositories accessible. Grant the GitHub App access to your repos.");
|
|
145
|
+
process.exitCode = 1;
|
|
146
|
+
outro("");
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
selectedRepo = await pickRepo(repos);
|
|
150
|
+
}
|
|
151
|
+
if (!selectedRepo) {
|
|
152
|
+
outro(pc.dim("Cancelled"));
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const s4 = args.json ? null : spinner();
|
|
156
|
+
s4?.start("Scanning repository...");
|
|
157
|
+
const scan = await client.scanRepository(installation.id, selectedRepo.fullName);
|
|
158
|
+
s4?.stop(scan.hasContentrain ? "Contentrain configuration found" : "No Contentrain configuration found");
|
|
159
|
+
if (!scan.hasContentrain) {
|
|
160
|
+
if (!args.json) {
|
|
161
|
+
log.warning("No .contentrain/ directory found in the repository.");
|
|
162
|
+
log.info(`Run ${pc.cyan("contentrain init")} in your project first, then push to ${selectedRepo.defaultBranch}.`);
|
|
163
|
+
}
|
|
164
|
+
const proceed = await confirm({ message: "Continue anyway? (You can initialize later)" });
|
|
165
|
+
if (isCancel(proceed) || !proceed) {
|
|
166
|
+
outro(pc.dim("Cancelled"));
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
} else if (!args.json) log.info(`Found ${scan.models.length} model(s), ${scan.locales.length} locale(s)`);
|
|
170
|
+
const projectName = await text({
|
|
171
|
+
message: "Project name",
|
|
172
|
+
initialValue: selectedRepo.fullName.split("/")[1] ?? selectedRepo.fullName,
|
|
173
|
+
validate: (v) => {
|
|
174
|
+
if (!v.trim()) return "Name is required";
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
if (isCancel(projectName)) {
|
|
178
|
+
outro(pc.dim("Cancelled"));
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const s5 = args.json ? null : spinner();
|
|
182
|
+
s5?.start("Creating project...");
|
|
183
|
+
const project = await client.createProject(workspaceId, {
|
|
184
|
+
name: projectName,
|
|
185
|
+
installationId: installation.id,
|
|
186
|
+
repositoryFullName: selectedRepo.fullName,
|
|
187
|
+
defaultBranch: selectedRepo.defaultBranch
|
|
188
|
+
});
|
|
189
|
+
s5?.stop("Project created");
|
|
190
|
+
await saveDefaults(workspaceId, project.id);
|
|
191
|
+
if (args.json) {
|
|
192
|
+
const output = {
|
|
193
|
+
workspace: {
|
|
194
|
+
id: workspace.id,
|
|
195
|
+
name: workspace.name
|
|
196
|
+
},
|
|
197
|
+
project: {
|
|
198
|
+
id: project.id,
|
|
199
|
+
name: project.name
|
|
200
|
+
},
|
|
201
|
+
repository: selectedRepo.fullName,
|
|
202
|
+
scan
|
|
203
|
+
};
|
|
204
|
+
process.stdout.write(JSON.stringify(output, null, 2));
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
log.success(pc.bold("Project connected!"));
|
|
208
|
+
log.message("");
|
|
209
|
+
log.message(` Workspace: ${pc.cyan(workspace.name)}`);
|
|
210
|
+
log.message(` Project: ${pc.cyan(project.name)}`);
|
|
211
|
+
log.message(` Repository: ${pc.cyan(selectedRepo.fullName)}`);
|
|
212
|
+
log.message(` Branch: ${selectedRepo.defaultBranch}`);
|
|
213
|
+
log.message("");
|
|
214
|
+
log.info("Next steps:");
|
|
215
|
+
log.message(` ${pc.cyan("contentrain studio status")} — view project overview`);
|
|
216
|
+
log.message(` ${pc.cyan("contentrain studio cdn-init")} — set up content delivery`);
|
|
217
|
+
log.message(` ${pc.cyan("contentrain studio webhooks")} — configure webhooks`);
|
|
218
|
+
} catch (error) {
|
|
219
|
+
log.error(error instanceof Error ? error.message : String(error));
|
|
220
|
+
process.exitCode = 1;
|
|
221
|
+
}
|
|
222
|
+
if (!args.json) outro("");
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
/**
|
|
226
|
+
* Parse owner/repo from a GitHub remote URL.
|
|
227
|
+
* Handles both SSH (git@github.com:owner/repo.git) and HTTPS formats.
|
|
228
|
+
*/
|
|
229
|
+
function parseGitHubRepoFromUrl(url) {
|
|
230
|
+
const sshMatch = url.match(/github\.com[:/]([^/]+\/[^/]+?)(?:\.git)?$/);
|
|
231
|
+
if (sshMatch) return sshMatch[1];
|
|
232
|
+
try {
|
|
233
|
+
const parsed = new URL(url);
|
|
234
|
+
if (parsed.hostname === "github.com") return parsed.pathname.replace(/^\//, "").replace(/\.git$/, "");
|
|
235
|
+
} catch {}
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
async function pickRepo(repos) {
|
|
239
|
+
if (repos.length === 0) return null;
|
|
240
|
+
const choice = await select({
|
|
241
|
+
message: "Select repository",
|
|
242
|
+
options: repos.map((r) => ({
|
|
243
|
+
value: r.fullName,
|
|
244
|
+
label: r.fullName,
|
|
245
|
+
hint: r.private ? "private" : "public"
|
|
246
|
+
}))
|
|
247
|
+
});
|
|
248
|
+
if (isCancel(choice)) return null;
|
|
249
|
+
return repos.find((r) => r.fullName === choice) ?? null;
|
|
250
|
+
}
|
|
251
|
+
//#endregion
|
|
252
|
+
export { connect_default as default };
|
|
@@ -141,6 +141,7 @@ var diff_default = defineCommand({
|
|
|
141
141
|
log.error(`Delete failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
142
142
|
}
|
|
143
143
|
}
|
|
144
|
+
log.message(pc.dim(`\n Tip: ${pc.cyan("contentrain studio branches")} — visual review and approval in ${pc.bold("Contentrain Studio")} → ${pc.underline("https://studio.contentrain.io")}`));
|
|
144
145
|
outro("");
|
|
145
146
|
}
|
|
146
147
|
});
|
|
@@ -41,6 +41,7 @@ var generate_default = defineCommand({
|
|
|
41
41
|
log.message(` Types: ${result.typesCount}`);
|
|
42
42
|
log.message(` Data: ${result.dataModulesCount} modules`);
|
|
43
43
|
if (result.packageJsonUpdated) log.info(`${pc.cyan("#contentrain")} imports added to package.json`);
|
|
44
|
+
log.message(pc.dim(`\n Tip: ${pc.cyan("contentrain studio cdn-init")} — deliver content via ${pc.bold("Contentrain Studio")} CDN → ${pc.underline("https://studio.contentrain.io")}`));
|
|
44
45
|
if (args.watch) {
|
|
45
46
|
log.info("Watching for changes... (Ctrl+C to stop)");
|
|
46
47
|
const crDir = contentrainDir(projectRoot);
|
package/dist/index.mjs
CHANGED
|
@@ -5,18 +5,18 @@ import { defineCommand, runMain } from "citty";
|
|
|
5
5
|
runMain(defineCommand({
|
|
6
6
|
meta: {
|
|
7
7
|
name: "contentrain",
|
|
8
|
-
version: "0.
|
|
8
|
+
version: "0.4.1",
|
|
9
9
|
description: "Contentrain CLI — AI content governance infrastructure"
|
|
10
10
|
},
|
|
11
11
|
subCommands: {
|
|
12
|
-
init: () => import("./init-
|
|
13
|
-
status: () => import("./status-
|
|
12
|
+
init: () => import("./init-Q9B0iYtu.mjs").then((m) => m.default),
|
|
13
|
+
status: () => import("./status-BmQZGdZX.mjs").then((m) => m.default),
|
|
14
14
|
doctor: () => import("./doctor-DyKjAIKH.mjs").then((m) => m.default),
|
|
15
15
|
validate: () => import("./validate-DnVamp3p.mjs").then((m) => m.default),
|
|
16
16
|
serve: () => import("./serve-DL4LhWxl.mjs").then((m) => m.default),
|
|
17
|
-
generate: () => import("./generate-
|
|
18
|
-
diff: () => import("./diff
|
|
19
|
-
studio: () => import("./studio-
|
|
17
|
+
generate: () => import("./generate-DrUojrk8.mjs").then((m) => m.default),
|
|
18
|
+
diff: () => import("./diff--halNUpG.mjs").then((m) => m.default),
|
|
19
|
+
studio: () => import("./studio-B8lF0fQx.mjs").then((m) => m.default)
|
|
20
20
|
}
|
|
21
21
|
}));
|
|
22
22
|
//#endregion
|
|
@@ -278,6 +278,9 @@ var init_default = defineCommand({
|
|
|
278
278
|
log.message(` ${pc.cyan("contentrain doctor")} — verify setup health`);
|
|
279
279
|
if (templateChoice === "none") log.message(` ${pc.cyan("contentrain serve")} — open the local review and normalize UI`);
|
|
280
280
|
log.message(` ${pc.cyan("contentrain generate")} — generate SDK client`);
|
|
281
|
+
log.message("");
|
|
282
|
+
log.message(pc.dim(` Tip: ${pc.cyan("contentrain studio connect")} — link this project to ${pc.bold("Contentrain Studio")} for`));
|
|
283
|
+
log.message(pc.dim(` team review, CDN delivery, and collaboration → ${pc.underline("https://studio.contentrain.io")}`));
|
|
281
284
|
outro("");
|
|
282
285
|
}
|
|
283
286
|
});
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { i as pc } from "./ui-B5mXontH.mjs";
|
|
2
|
+
import { i as checkPermissions, o as loadCredentials, s as saveCredentials, t as StudioApiClient } from "./client-CLV4XoJz.mjs";
|
|
3
|
+
import { n as openBrowser, t as startOAuthServer } from "./oauth-server-1p6y1H30.mjs";
|
|
4
|
+
import { defineCommand } from "citty";
|
|
5
|
+
import { confirm, intro, isCancel, log, outro, select, spinner } from "@clack/prompts";
|
|
6
|
+
//#region src/studio/commands/login.ts
|
|
7
|
+
const DEFAULT_STUDIO_URL = "https://studio.contentrain.io";
|
|
8
|
+
var login_default = defineCommand({
|
|
9
|
+
meta: {
|
|
10
|
+
name: "login",
|
|
11
|
+
description: "Authenticate with Contentrain Studio"
|
|
12
|
+
},
|
|
13
|
+
args: {
|
|
14
|
+
url: {
|
|
15
|
+
type: "string",
|
|
16
|
+
description: "Studio instance URL",
|
|
17
|
+
required: false
|
|
18
|
+
},
|
|
19
|
+
provider: {
|
|
20
|
+
type: "string",
|
|
21
|
+
description: "OAuth provider (github or google)",
|
|
22
|
+
required: false
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
async run({ args }) {
|
|
26
|
+
intro(pc.bold("contentrain studio login"));
|
|
27
|
+
try {
|
|
28
|
+
const studioUrl = (args.url ?? process.env["CONTENTRAIN_STUDIO_URL"] ?? DEFAULT_STUDIO_URL).replace(/\/+$/, "");
|
|
29
|
+
if (await loadCredentials()) {
|
|
30
|
+
const reAuth = await confirm({ message: "You are already logged in. Re-authenticate?" });
|
|
31
|
+
if (isCancel(reAuth) || !reAuth) {
|
|
32
|
+
outro(pc.dim("Cancelled"));
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
let provider = args.provider;
|
|
37
|
+
if (!provider) {
|
|
38
|
+
const choice = await select({
|
|
39
|
+
message: "Sign in with",
|
|
40
|
+
options: [{
|
|
41
|
+
value: "github",
|
|
42
|
+
label: "GitHub"
|
|
43
|
+
}, {
|
|
44
|
+
value: "google",
|
|
45
|
+
label: "Google"
|
|
46
|
+
}]
|
|
47
|
+
});
|
|
48
|
+
if (isCancel(choice)) {
|
|
49
|
+
outro(pc.dim("Cancelled"));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
provider = choice;
|
|
53
|
+
}
|
|
54
|
+
const s = spinner();
|
|
55
|
+
s.start("Starting authentication...");
|
|
56
|
+
const oauth = await startOAuthServer();
|
|
57
|
+
const loginUrl = `${studioUrl}/api/auth/login?provider=${provider}&redirect_uri=${encodeURIComponent(oauth.callbackUrl)}&state=${oauth.state}`;
|
|
58
|
+
s.stop("Opening browser...");
|
|
59
|
+
log.info(`If the browser doesn't open, visit:\n ${pc.cyan(loginUrl)}`);
|
|
60
|
+
await openBrowser(loginUrl);
|
|
61
|
+
const s2 = spinner();
|
|
62
|
+
s2.start("Waiting for authentication...");
|
|
63
|
+
let result;
|
|
64
|
+
try {
|
|
65
|
+
result = await oauth.waitForCallback();
|
|
66
|
+
} catch (error) {
|
|
67
|
+
s2.stop("Failed");
|
|
68
|
+
oauth.close();
|
|
69
|
+
log.error(error instanceof Error ? error.message : String(error));
|
|
70
|
+
process.exitCode = 1;
|
|
71
|
+
outro("");
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (result.state !== oauth.state) {
|
|
75
|
+
s2.stop("Failed");
|
|
76
|
+
log.error("OAuth state mismatch. This could be a CSRF attack. Please try again.");
|
|
77
|
+
process.exitCode = 1;
|
|
78
|
+
outro("");
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
s2.stop("Exchanging token...");
|
|
82
|
+
const s3 = spinner();
|
|
83
|
+
s3.start("Completing authentication...");
|
|
84
|
+
const verifyRes = await globalThis.fetch(`${studioUrl}/api/auth/verify`, {
|
|
85
|
+
method: "POST",
|
|
86
|
+
headers: { "Content-Type": "application/json" },
|
|
87
|
+
body: JSON.stringify({
|
|
88
|
+
code: result.code,
|
|
89
|
+
state: result.state,
|
|
90
|
+
redirectUri: oauth.callbackUrl
|
|
91
|
+
})
|
|
92
|
+
});
|
|
93
|
+
if (!verifyRes.ok) {
|
|
94
|
+
s3.stop("Failed");
|
|
95
|
+
log.error("Token exchange failed. Please try again.");
|
|
96
|
+
process.exitCode = 1;
|
|
97
|
+
outro("");
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const tokenData = await verifyRes.json();
|
|
101
|
+
await saveCredentials({
|
|
102
|
+
studioUrl,
|
|
103
|
+
accessToken: tokenData.accessToken,
|
|
104
|
+
refreshToken: tokenData.refreshToken,
|
|
105
|
+
expiresAt: tokenData.expiresAt
|
|
106
|
+
});
|
|
107
|
+
const user = await new StudioApiClient({
|
|
108
|
+
studioUrl,
|
|
109
|
+
accessToken: tokenData.accessToken,
|
|
110
|
+
refreshToken: tokenData.refreshToken,
|
|
111
|
+
expiresAt: tokenData.expiresAt
|
|
112
|
+
}).me();
|
|
113
|
+
s3.stop("Authenticated");
|
|
114
|
+
log.success(`Logged in as ${pc.bold(user.email)}`);
|
|
115
|
+
const permWarning = await checkPermissions();
|
|
116
|
+
if (permWarning) log.warning(permWarning);
|
|
117
|
+
} catch (error) {
|
|
118
|
+
log.error(error instanceof Error ? error.message : String(error));
|
|
119
|
+
process.exitCode = 1;
|
|
120
|
+
}
|
|
121
|
+
outro("");
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
//#endregion
|
|
125
|
+
export { login_default as default };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as pc } from "./ui-B5mXontH.mjs";
|
|
2
|
-
import { a as clearCredentials, o as loadCredentials, t as StudioApiClient } from "./client-
|
|
2
|
+
import { a as clearCredentials, o as loadCredentials, t as StudioApiClient } from "./client-CLV4XoJz.mjs";
|
|
3
3
|
import { defineCommand } from "citty";
|
|
4
4
|
import { intro, log, outro } from "@clack/prompts";
|
|
5
5
|
//#region src/studio/commands/logout.ts
|
|
@@ -1,9 +1,19 @@
|
|
|
1
|
-
import { i as pc } from "./ui-B5mXontH.mjs";
|
|
2
|
-
import { i as checkPermissions, o as loadCredentials, s as saveCredentials, t as StudioApiClient } from "./client-D4xW8aLz.mjs";
|
|
3
|
-
import { defineCommand } from "citty";
|
|
4
|
-
import { confirm, intro, isCancel, log, outro, select, spinner } from "@clack/prompts";
|
|
5
1
|
import { randomUUID } from "node:crypto";
|
|
6
2
|
import { createServer } from "node:http";
|
|
3
|
+
//#region src/utils/browser.ts
|
|
4
|
+
/**
|
|
5
|
+
* Open a URL in the user's default browser (best-effort, platform-aware).
|
|
6
|
+
*/
|
|
7
|
+
async function openBrowser(url) {
|
|
8
|
+
const { exec } = await import("node:child_process");
|
|
9
|
+
const command = process.platform === "darwin" ? `open "${url}"` : process.platform === "win32" ? `start "" "${url}"` : `xdg-open "${url}"`;
|
|
10
|
+
return new Promise((resolve) => {
|
|
11
|
+
exec(command, () => {
|
|
12
|
+
resolve();
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
7
17
|
//#region src/studio/auth/oauth-server.ts
|
|
8
18
|
const PORT_RANGE_START = 9876;
|
|
9
19
|
const PORT_RANGE_END = 9899;
|
|
@@ -112,132 +122,4 @@ function closeServer(server) {
|
|
|
112
122
|
} catch {}
|
|
113
123
|
}
|
|
114
124
|
//#endregion
|
|
115
|
-
|
|
116
|
-
const DEFAULT_STUDIO_URL = "https://studio.contentrain.io";
|
|
117
|
-
var login_default = defineCommand({
|
|
118
|
-
meta: {
|
|
119
|
-
name: "login",
|
|
120
|
-
description: "Authenticate with Contentrain Studio"
|
|
121
|
-
},
|
|
122
|
-
args: {
|
|
123
|
-
url: {
|
|
124
|
-
type: "string",
|
|
125
|
-
description: "Studio instance URL",
|
|
126
|
-
required: false
|
|
127
|
-
},
|
|
128
|
-
provider: {
|
|
129
|
-
type: "string",
|
|
130
|
-
description: "OAuth provider (github or google)",
|
|
131
|
-
required: false
|
|
132
|
-
}
|
|
133
|
-
},
|
|
134
|
-
async run({ args }) {
|
|
135
|
-
intro(pc.bold("contentrain studio login"));
|
|
136
|
-
try {
|
|
137
|
-
const studioUrl = (args.url ?? process.env["CONTENTRAIN_STUDIO_URL"] ?? DEFAULT_STUDIO_URL).replace(/\/+$/, "");
|
|
138
|
-
if (await loadCredentials()) {
|
|
139
|
-
const reAuth = await confirm({ message: "You are already logged in. Re-authenticate?" });
|
|
140
|
-
if (isCancel(reAuth) || !reAuth) {
|
|
141
|
-
outro(pc.dim("Cancelled"));
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
let provider = args.provider;
|
|
146
|
-
if (!provider) {
|
|
147
|
-
const choice = await select({
|
|
148
|
-
message: "Sign in with",
|
|
149
|
-
options: [{
|
|
150
|
-
value: "github",
|
|
151
|
-
label: "GitHub"
|
|
152
|
-
}, {
|
|
153
|
-
value: "google",
|
|
154
|
-
label: "Google"
|
|
155
|
-
}]
|
|
156
|
-
});
|
|
157
|
-
if (isCancel(choice)) {
|
|
158
|
-
outro(pc.dim("Cancelled"));
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
provider = choice;
|
|
162
|
-
}
|
|
163
|
-
const s = spinner();
|
|
164
|
-
s.start("Starting authentication...");
|
|
165
|
-
const oauth = await startOAuthServer();
|
|
166
|
-
const loginUrl = `${studioUrl}/api/auth/login?provider=${provider}&redirect_uri=${encodeURIComponent(oauth.callbackUrl)}&state=${oauth.state}`;
|
|
167
|
-
s.stop("Opening browser...");
|
|
168
|
-
log.info(`If the browser doesn't open, visit:\n ${pc.cyan(loginUrl)}`);
|
|
169
|
-
await openBrowser(loginUrl);
|
|
170
|
-
const s2 = spinner();
|
|
171
|
-
s2.start("Waiting for authentication...");
|
|
172
|
-
let result;
|
|
173
|
-
try {
|
|
174
|
-
result = await oauth.waitForCallback();
|
|
175
|
-
} catch (error) {
|
|
176
|
-
s2.stop("Failed");
|
|
177
|
-
oauth.close();
|
|
178
|
-
log.error(error instanceof Error ? error.message : String(error));
|
|
179
|
-
process.exitCode = 1;
|
|
180
|
-
outro("");
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
if (result.state !== oauth.state) {
|
|
184
|
-
s2.stop("Failed");
|
|
185
|
-
log.error("OAuth state mismatch. This could be a CSRF attack. Please try again.");
|
|
186
|
-
process.exitCode = 1;
|
|
187
|
-
outro("");
|
|
188
|
-
return;
|
|
189
|
-
}
|
|
190
|
-
s2.stop("Exchanging token...");
|
|
191
|
-
const s3 = spinner();
|
|
192
|
-
s3.start("Completing authentication...");
|
|
193
|
-
const verifyRes = await globalThis.fetch(`${studioUrl}/api/auth/verify`, {
|
|
194
|
-
method: "POST",
|
|
195
|
-
headers: { "Content-Type": "application/json" },
|
|
196
|
-
body: JSON.stringify({
|
|
197
|
-
code: result.code,
|
|
198
|
-
state: result.state,
|
|
199
|
-
redirectUri: oauth.callbackUrl
|
|
200
|
-
})
|
|
201
|
-
});
|
|
202
|
-
if (!verifyRes.ok) {
|
|
203
|
-
s3.stop("Failed");
|
|
204
|
-
log.error("Token exchange failed. Please try again.");
|
|
205
|
-
process.exitCode = 1;
|
|
206
|
-
outro("");
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
const tokenData = await verifyRes.json();
|
|
210
|
-
await saveCredentials({
|
|
211
|
-
studioUrl,
|
|
212
|
-
accessToken: tokenData.accessToken,
|
|
213
|
-
refreshToken: tokenData.refreshToken,
|
|
214
|
-
expiresAt: tokenData.expiresAt
|
|
215
|
-
});
|
|
216
|
-
const user = await new StudioApiClient({
|
|
217
|
-
studioUrl,
|
|
218
|
-
accessToken: tokenData.accessToken,
|
|
219
|
-
refreshToken: tokenData.refreshToken,
|
|
220
|
-
expiresAt: tokenData.expiresAt
|
|
221
|
-
}).me();
|
|
222
|
-
s3.stop("Authenticated");
|
|
223
|
-
log.success(`Logged in as ${pc.bold(user.email)}`);
|
|
224
|
-
const permWarning = await checkPermissions();
|
|
225
|
-
if (permWarning) log.warning(permWarning);
|
|
226
|
-
} catch (error) {
|
|
227
|
-
log.error(error instanceof Error ? error.message : String(error));
|
|
228
|
-
process.exitCode = 1;
|
|
229
|
-
}
|
|
230
|
-
outro("");
|
|
231
|
-
}
|
|
232
|
-
});
|
|
233
|
-
async function openBrowser(url) {
|
|
234
|
-
const { exec } = await import("node:child_process");
|
|
235
|
-
const command = process.platform === "darwin" ? `open "${url}"` : process.platform === "win32" ? `start "" "${url}"` : `xdg-open "${url}"`;
|
|
236
|
-
return new Promise((resolve) => {
|
|
237
|
-
exec(command, () => {
|
|
238
|
-
resolve();
|
|
239
|
-
});
|
|
240
|
-
});
|
|
241
|
-
}
|
|
242
|
-
//#endregion
|
|
243
|
-
export { login_default as default };
|
|
125
|
+
export { openBrowser as n, startOAuthServer as t };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as saveDefaults, o as loadCredentials } from "./client-
|
|
1
|
+
import { c as saveDefaults, o as loadCredentials } from "./client-CLV4XoJz.mjs";
|
|
2
2
|
import { confirm, isCancel, select } from "@clack/prompts";
|
|
3
3
|
//#region src/studio/resolve-context.ts
|
|
4
4
|
/**
|
|
@@ -148,6 +148,7 @@ var status_default = defineCommand({
|
|
|
148
148
|
if (result.summary.errors > 0) log.warning(`\n${formatCount(result.summary.errors, "validation error")}. Run ${pc.cyan("contentrain validate --fix")} to fix.`);
|
|
149
149
|
else log.success("\nValidation: clean");
|
|
150
150
|
} catch {}
|
|
151
|
+
log.message(pc.dim(`\n Tip: ${pc.cyan("contentrain studio status")} — team activity, usage, and CDN in ${pc.bold("Contentrain Studio")} → ${pc.underline("https://studio.contentrain.io")}`));
|
|
151
152
|
outro("");
|
|
152
153
|
}
|
|
153
154
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { i as pc, r as formatTable, t as formatCount } from "./ui-B5mXontH.mjs";
|
|
2
|
-
import { n as resolveStudioClient } from "./client-
|
|
3
|
-
import { t as resolveStudioContext } from "./resolve-context-
|
|
2
|
+
import { n as resolveStudioClient } from "./client-CLV4XoJz.mjs";
|
|
3
|
+
import { t as resolveStudioContext } from "./resolve-context-BwcikcF0.mjs";
|
|
4
4
|
import { defineCommand } from "citty";
|
|
5
5
|
import { intro, log, outro, spinner } from "@clack/prompts";
|
|
6
6
|
//#region src/studio/commands/status.ts
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { defineCommand } from "citty";
|
|
2
|
+
//#region src/studio/index.ts
|
|
3
|
+
var studio_default = defineCommand({
|
|
4
|
+
meta: {
|
|
5
|
+
name: "studio",
|
|
6
|
+
description: "Interact with Contentrain Studio"
|
|
7
|
+
},
|
|
8
|
+
subCommands: {
|
|
9
|
+
login: () => import("./login-wRBvHDCi.mjs").then((m) => m.default),
|
|
10
|
+
logout: () => import("./logout-xPTGu6vx.mjs").then((m) => m.default),
|
|
11
|
+
whoami: () => import("./whoami-CWvTYzum.mjs").then((m) => m.default),
|
|
12
|
+
connect: () => import("./connect-DiSYnxFd.mjs").then((m) => m.default),
|
|
13
|
+
status: () => import("./status-UvjbO4eS.mjs").then((m) => m.default),
|
|
14
|
+
activity: () => import("./activity-DMQsYlzz.mjs").then((m) => m.default),
|
|
15
|
+
usage: () => import("./usage-BqriRRqE.mjs").then((m) => m.default),
|
|
16
|
+
branches: () => import("./branches-D330IxDO.mjs").then((m) => m.default),
|
|
17
|
+
"cdn-init": () => import("./cdn-init-Bhnil0F8.mjs").then((m) => m.default),
|
|
18
|
+
"cdn-build": () => import("./cdn-build-D_d3p4OZ.mjs").then((m) => m.default),
|
|
19
|
+
webhooks: () => import("./webhooks-B1OhcCtZ.mjs").then((m) => m.default),
|
|
20
|
+
submissions: () => import("./submissions-Dw0ChFDi.mjs").then((m) => m.default)
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
//#endregion
|
|
24
|
+
export { studio_default as default };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { i as pc, r as formatTable, t as formatCount } from "./ui-B5mXontH.mjs";
|
|
2
|
-
import { n as resolveStudioClient } from "./client-
|
|
3
|
-
import { t as resolveStudioContext } from "./resolve-context-
|
|
2
|
+
import { n as resolveStudioClient } from "./client-CLV4XoJz.mjs";
|
|
3
|
+
import { t as resolveStudioContext } from "./resolve-context-BwcikcF0.mjs";
|
|
4
4
|
import { defineCommand } from "citty";
|
|
5
5
|
import { confirm, intro, isCancel, log, outro, select, spinner } from "@clack/prompts";
|
|
6
6
|
//#region src/studio/commands/submissions.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { i as pc, n as formatPercent, r as formatTable } from "./ui-B5mXontH.mjs";
|
|
2
|
-
import { n as resolveStudioClient } from "./client-
|
|
3
|
-
import { t as resolveStudioContext } from "./resolve-context-
|
|
2
|
+
import { n as resolveStudioClient } from "./client-CLV4XoJz.mjs";
|
|
3
|
+
import { t as resolveStudioContext } from "./resolve-context-BwcikcF0.mjs";
|
|
4
4
|
import { defineCommand } from "citty";
|
|
5
5
|
import { intro, log, outro, spinner } from "@clack/prompts";
|
|
6
6
|
//#region src/studio/commands/usage.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { i as pc, o as statusIcon, r as formatTable } from "./ui-B5mXontH.mjs";
|
|
2
|
-
import { n as resolveStudioClient } from "./client-
|
|
3
|
-
import { t as resolveStudioContext } from "./resolve-context-
|
|
2
|
+
import { n as resolveStudioClient } from "./client-CLV4XoJz.mjs";
|
|
3
|
+
import { t as resolveStudioContext } from "./resolve-context-BwcikcF0.mjs";
|
|
4
4
|
import { defineCommand } from "citty";
|
|
5
5
|
import { confirm, intro, isCancel, log, multiselect, outro, select, spinner, text } from "@clack/prompts";
|
|
6
6
|
//#region src/studio/commands/webhooks.ts
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as pc } from "./ui-B5mXontH.mjs";
|
|
2
|
-
import { i as checkPermissions, n as resolveStudioClient, r as AuthExpiredError } from "./client-
|
|
2
|
+
import { i as checkPermissions, n as resolveStudioClient, r as AuthExpiredError } from "./client-CLV4XoJz.mjs";
|
|
3
3
|
import { defineCommand } from "citty";
|
|
4
4
|
import { intro, log, outro } from "@clack/prompts";
|
|
5
5
|
//#region src/studio/commands/whoami.ts
|
package/package.json
CHANGED
package/dist/studio-BmXS_bCq.mjs
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { defineCommand } from "citty";
|
|
2
|
-
//#region src/studio/index.ts
|
|
3
|
-
var studio_default = defineCommand({
|
|
4
|
-
meta: {
|
|
5
|
-
name: "studio",
|
|
6
|
-
description: "Interact with Contentrain Studio"
|
|
7
|
-
},
|
|
8
|
-
subCommands: {
|
|
9
|
-
login: () => import("./login-CO0hxICh.mjs").then((m) => m.default),
|
|
10
|
-
logout: () => import("./logout-CRM4fCSH.mjs").then((m) => m.default),
|
|
11
|
-
whoami: () => import("./whoami-D8NyFKs_.mjs").then((m) => m.default),
|
|
12
|
-
status: () => import("./status-ts5FvDEZ.mjs").then((m) => m.default),
|
|
13
|
-
activity: () => import("./activity-CtOcAA4X.mjs").then((m) => m.default),
|
|
14
|
-
usage: () => import("./usage-BAb4q7Pz.mjs").then((m) => m.default),
|
|
15
|
-
branches: () => import("./branches-C_kgqSv9.mjs").then((m) => m.default),
|
|
16
|
-
"cdn-init": () => import("./cdn-init-DXQ-3V_c.mjs").then((m) => m.default),
|
|
17
|
-
"cdn-build": () => import("./cdn-build-CDv_yM15.mjs").then((m) => m.default),
|
|
18
|
-
webhooks: () => import("./webhooks-C39IItU1.mjs").then((m) => m.default),
|
|
19
|
-
submissions: () => import("./submissions-6_OCrUNF.mjs").then((m) => m.default)
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
//#endregion
|
|
23
|
-
export { studio_default as default };
|