@kici-dev/compiler 0.0.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/README.md +1 -6
- package/dist/assets/api-TJJVHrjC.json +118 -0
- package/dist/assets/descriptor-BTtjzN9L.json +1382 -0
- package/dist/assets/package-BpQF9kR8.json +74 -0
- package/dist/assets/package-Ceo2h27X.json +89 -0
- package/dist/assets/source_context-D0atuL28.json +20 -0
- package/dist/assets/type-BFqO8SCZ.json +202 -0
- package/dist/auth/headless-detect.d.ts +14 -0
- package/dist/auth/headless-detect.js +25 -0
- package/dist/chunk-gOLHoazu.js +4 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +193 -0
- package/dist/commands/cancel.d.ts +22 -0
- package/dist/commands/cancel.js +124 -0
- package/dist/commands/compile.d.ts +17 -0
- package/dist/commands/compile.js +99 -0
- package/dist/commands/docs.d.ts +26 -0
- package/dist/commands/docs.js +60 -0
- package/dist/commands/drain-worker.d.ts +19 -0
- package/dist/commands/drain-worker.js +45 -0
- package/dist/commands/endpoints.d.ts +53 -0
- package/dist/commands/endpoints.js +185 -0
- package/dist/commands/fixture.d.ts +14 -0
- package/dist/commands/fixture.js +104 -0
- package/dist/commands/hook.d.ts +20 -0
- package/dist/commands/hook.js +97 -0
- package/dist/commands/index.d.ts +33 -0
- package/dist/commands/index.js +20 -0
- package/dist/commands/init.d.ts +35 -0
- package/dist/commands/init.js +393 -0
- package/dist/commands/login.d.ts +23 -0
- package/dist/commands/login.js +144 -0
- package/dist/commands/logout.d.ts +18 -0
- package/dist/commands/logout.js +55 -0
- package/dist/commands/org.d.ts +27 -0
- package/dist/commands/org.js +126 -0
- package/dist/commands/run.d.ts +21 -0
- package/dist/commands/run.js +562 -0
- package/dist/commands/secrets-list.d.ts +16 -0
- package/dist/commands/secrets-list.js +85 -0
- package/dist/commands/status.d.ts +30 -0
- package/dist/commands/status.js +210 -0
- package/dist/commands/test.d.ts +61 -0
- package/dist/commands/test.js +220 -0
- package/dist/commands/types.d.ts +18 -0
- package/dist/commands/types.js +74 -0
- package/dist/commands/watch.d.ts +14 -0
- package/dist/commands/watch.js +97 -0
- package/dist/commands/workflows.d.ts +28 -0
- package/dist/commands/workflows.js +154 -0
- package/dist/comment-created.json +30 -0
- package/dist/create-branch.json +17 -0
- package/dist/delete-branch.json +15 -0
- package/dist/dispatch.json +15 -0
- package/dist/errors/capability-gap.d.ts +50 -0
- package/dist/errors/capability-gap.js +54 -0
- package/dist/errors/codes.d.ts +25 -0
- package/dist/errors/formatter.d.ts +32 -0
- package/dist/errors/formatter.js +35 -0
- package/dist/errors/index.d.ts +5 -0
- package/dist/errors/index.js +4 -0
- package/dist/execution/executor.d.ts +61 -0
- package/dist/execution/executor.js +230 -0
- package/dist/execution/index.d.ts +4 -0
- package/dist/execution/index.js +3 -0
- package/dist/execution/sdk-alias.d.ts +33 -0
- package/dist/execution/sdk-alias.js +102 -0
- package/dist/fixtures/compiler.d.ts +47 -0
- package/dist/fixtures/compiler.js +177 -0
- package/dist/fixtures/defaults/comment-created.json +30 -0
- package/dist/fixtures/defaults/create-branch.json +17 -0
- package/dist/fixtures/defaults/delete-branch.json +15 -0
- package/dist/fixtures/defaults/dispatch.json +15 -0
- package/dist/fixtures/defaults/fork.json +19 -0
- package/dist/fixtures/defaults/index.d.ts +16 -0
- package/dist/fixtures/defaults/index.js +105 -0
- package/dist/fixtures/defaults/index.ts +145 -0
- package/dist/fixtures/defaults/pr-closed.json +28 -0
- package/dist/fixtures/defaults/pr-opened.json +27 -0
- package/dist/fixtures/defaults/pr-reopened.json +27 -0
- package/dist/fixtures/defaults/pr-synchronize.json +27 -0
- package/dist/fixtures/defaults/push.json +16 -0
- package/dist/fixtures/defaults/release-published.json +23 -0
- package/dist/fixtures/defaults/review-comment-created.json +36 -0
- package/dist/fixtures/defaults/review-submitted.json +35 -0
- package/dist/fixtures/defaults/star-created.json +15 -0
- package/dist/fixtures/defaults/status.json +26 -0
- package/dist/fixtures/defaults/tag-push.json +20 -0
- package/dist/fixtures/defaults/watch-started.json +15 -0
- package/dist/fixtures/defaults/workflow-run-completed.json +23 -0
- package/dist/fork.json +19 -0
- package/dist/format.d.ts +5 -0
- package/dist/format.js +20 -0
- package/dist/generators/secrets-dts.d.ts +29 -0
- package/dist/generators/secrets-dts.js +67 -0
- package/dist/hooks/detector.d.ts +39 -0
- package/dist/hooks/detector.js +133 -0
- package/dist/hooks/index.d.ts +6 -0
- package/dist/hooks/index.js +5 -0
- package/dist/hooks/installer.d.ts +24 -0
- package/dist/hooks/installer.js +328 -0
- package/dist/hooks/templates.d.ts +26 -0
- package/dist/hooks/templates.js +63 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +12 -0
- package/dist/llm-context/llms-full.txt +9974 -0
- package/dist/llm-context/llms.txt +61 -0
- package/dist/local-executor/dag-scheduler.d.ts +44 -0
- package/dist/local-executor/dag-scheduler.js +183 -0
- package/dist/local-executor/index.d.ts +23 -0
- package/dist/local-executor/index.js +309 -0
- package/dist/local-executor/job-runner.d.ts +40 -0
- package/dist/local-executor/job-runner.js +307 -0
- package/dist/local-executor/output-streamer.d.ts +31 -0
- package/dist/local-executor/output-streamer.js +166 -0
- package/dist/local-executor/payload-generator.d.ts +16 -0
- package/dist/local-executor/payload-generator.js +138 -0
- package/dist/local-executor/picker.d.ts +33 -0
- package/dist/local-executor/picker.js +109 -0
- package/dist/local-executor/secret-loader.d.ts +18 -0
- package/dist/local-executor/secret-loader.js +105 -0
- package/dist/local-executor/types.d.ts +80 -0
- package/dist/local-executor/types.js +2 -0
- package/dist/local-executor/workflow-lock.d.ts +81 -0
- package/dist/local-executor/workflow-lock.js +0 -0
- package/dist/lockfile/generator.d.ts +39 -0
- package/dist/lockfile/generator.js +688 -0
- package/dist/lockfile/hash-files.d.ts +14 -0
- package/dist/lockfile/hash-files.js +50 -0
- package/dist/lockfile/hasher.d.ts +36 -0
- package/dist/lockfile/hasher.js +46 -0
- package/dist/lockfile/index.d.ts +3 -0
- package/dist/lockfile/index.js +4 -0
- package/dist/lockfile/purity-analyzer.d.ts +25 -0
- package/dist/lockfile/purity-analyzer.js +204 -0
- package/dist/package-F7UXSDHW.json +74 -0
- package/dist/postinstall.d.ts +9 -0
- package/dist/postinstall.js +60 -0
- package/dist/pr-closed.json +28 -0
- package/dist/pr-opened.json +27 -0
- package/dist/pr-reopened.json +27 -0
- package/dist/pr-synchronize.json +27 -0
- package/dist/push.json +16 -0
- package/dist/release-published.json +23 -0
- package/dist/remote/client.d.ts +204 -0
- package/dist/remote/client.js +203 -0
- package/dist/remote/config.d.ts +54 -0
- package/dist/remote/config.js +92 -0
- package/dist/remote/encryption.d.ts +35 -0
- package/dist/remote/encryption.js +87 -0
- package/dist/remote/history.d.ts +91 -0
- package/dist/remote/history.js +146 -0
- package/dist/remote/oauth.d.ts +65 -0
- package/dist/remote/oauth.js +302 -0
- package/dist/remote/observer.d.ts +81 -0
- package/dist/remote/observer.js +174 -0
- package/dist/remote/output/json.d.ts +13 -0
- package/dist/remote/output/json.js +36 -0
- package/dist/remote/output/junit.d.ts +18 -0
- package/dist/remote/output/junit.js +50 -0
- package/dist/remote/output/streaming.d.ts +57 -0
- package/dist/remote/output/streaming.js +124 -0
- package/dist/remote/output/summary.d.ts +39 -0
- package/dist/remote/output/summary.js +99 -0
- package/dist/remote/uploader.d.ts +87 -0
- package/dist/remote/uploader.js +197 -0
- package/dist/review-comment-created.json +36 -0
- package/dist/review-submitted.json +35 -0
- package/dist/star-created.json +15 -0
- package/dist/status.json +26 -0
- package/dist/tag-push.json +20 -0
- package/dist/templates/agents-md.d.ts +8 -0
- package/dist/templates/agents-md.js +130 -0
- package/dist/templates/index.d.ts +43 -0
- package/dist/templates/index.js +48 -0
- package/dist/templates/package-json.d.ts +18 -0
- package/dist/templates/package-json.js +34 -0
- package/dist/templates/tsconfig-json.d.ts +9 -0
- package/dist/templates/tsconfig-json.js +26 -0
- package/dist/templates/workflows/hello-world.d.ts +2 -0
- package/dist/templates/workflows/hello-world.js +16 -0
- package/dist/templates/workflows/hello-world.ts +21 -0
- package/dist/templates/workflows/pr-checks.d.ts +2 -0
- package/dist/templates/workflows/pr-checks.js +40 -0
- package/dist/templates/workflows/pr-checks.ts +57 -0
- package/dist/test-runner/dry-run.d.ts +12 -0
- package/dist/test-runner/dry-run.js +66 -0
- package/dist/test-runner/event-types.d.ts +86 -0
- package/dist/test-runner/event-types.js +330 -0
- package/dist/test-runner/git-detector.d.ts +15 -0
- package/dist/test-runner/git-detector.js +30 -0
- package/dist/test-runner/index.d.ts +13 -0
- package/dist/test-runner/index.js +11 -0
- package/dist/test-runner/job-executor.d.ts +48 -0
- package/dist/test-runner/job-executor.js +245 -0
- package/dist/test-runner/output-formatter.d.ts +47 -0
- package/dist/test-runner/output-formatter.js +92 -0
- package/dist/test-runner/payload-builder.d.ts +20 -0
- package/dist/test-runner/payload-builder.js +216 -0
- package/dist/test-runner/rule-evaluator.d.ts +14 -0
- package/dist/test-runner/rule-evaluator.js +31 -0
- package/dist/test-runner/secrets-file.d.ts +24 -0
- package/dist/test-runner/secrets-file.js +62 -0
- package/dist/test-runner/step-context.d.ts +15 -0
- package/dist/test-runner/step-context.js +140 -0
- package/dist/test-runner/summary.d.ts +7 -0
- package/dist/types.d.ts +525 -0
- package/dist/types.js +33 -0
- package/dist/validation/index.d.ts +3 -0
- package/dist/validation/index.js +3 -0
- package/dist/validation/validator.d.ts +26 -0
- package/dist/validation/validator.js +164 -0
- package/dist/watch-started.json +15 -0
- package/dist/workflow-run-completed.json +23 -0
- package/dist/workflows/hello-world.ts +21 -0
- package/dist/workflows/pr-checks.ts +57 -0
- package/hack/postinstall.mjs +105 -0
- package/package.json +60 -6
- package/sbom.spdx.json +10997 -0
- package/index.js +0 -3
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
import "../chunk-gOLHoazu.js";
|
|
2
|
+
import { tsconfigTemplate } from "../templates/tsconfig-json.js";
|
|
3
|
+
import { generatePackageJson } from "../templates/package-json.js";
|
|
4
|
+
import { agentsMdTemplate } from "../templates/agents-md.js";
|
|
5
|
+
import { workflowPaths } from "../templates/index.js";
|
|
6
|
+
import { getTypeScriptPaths } from "../execution/sdk-alias.js";
|
|
7
|
+
import { detectHookTools, findGitDir } from "../hooks/detector.js";
|
|
8
|
+
import { installHook } from "../hooks/installer.js";
|
|
9
|
+
import "../hooks/index.js";
|
|
10
|
+
import pc from "picocolors";
|
|
11
|
+
import { access, mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
12
|
+
import path from "node:path";
|
|
13
|
+
import { initZx, logger, toErrorMessage } from "@kici-dev/shared";
|
|
14
|
+
import { $ } from "zx";
|
|
15
|
+
import { checkbox, confirm, select } from "@inquirer/prompts";
|
|
16
|
+
//#region src/commands/init.ts
|
|
17
|
+
/**
|
|
18
|
+
* kici init command
|
|
19
|
+
*
|
|
20
|
+
* Creates .kici/ directory structure with workflow templates.
|
|
21
|
+
* Supports TypeScript mode (with package.json/node_modules) and MJS mode (pure JS).
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* Initialize .kici/ directory with workflow templates
|
|
25
|
+
*
|
|
26
|
+
* @param options - Configuration options for initialization
|
|
27
|
+
* @returns true on success, false on error
|
|
28
|
+
*/
|
|
29
|
+
async function initCommand(options = {}) {
|
|
30
|
+
initZx();
|
|
31
|
+
try {
|
|
32
|
+
const kiciDir = path.resolve(".kici");
|
|
33
|
+
const exists = await checkExists(kiciDir);
|
|
34
|
+
if (exists && !options.force) {
|
|
35
|
+
logger.error(pc.red("\nError: .kici/ directory already exists."));
|
|
36
|
+
logger.error(pc.gray("Use --force to overwrite.\n"));
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
if (exists && options.force) {
|
|
40
|
+
logger.info(pc.yellow("Removing existing .kici/ directory..."));
|
|
41
|
+
await rm(kiciDir, {
|
|
42
|
+
recursive: true,
|
|
43
|
+
force: true
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
const workflows = await selectWorkflows();
|
|
47
|
+
logger.info(pc.cyan("\nInitializing kici...\n"));
|
|
48
|
+
logger.info(pc.gray("Creating .kici/"));
|
|
49
|
+
await mkdir(kiciDir, { recursive: true });
|
|
50
|
+
logger.info(pc.gray("Creating .kici/workflows/"));
|
|
51
|
+
await mkdir(path.join(kiciDir, "workflows"), { recursive: true });
|
|
52
|
+
const defaultBranch = await detectDefaultBranch();
|
|
53
|
+
for (const workflow of workflows) {
|
|
54
|
+
logger.info(pc.gray(`Writing .kici/workflows/${workflow}.ts`));
|
|
55
|
+
const sourcePath = workflowPaths[workflow];
|
|
56
|
+
let content = await readFile(sourcePath, "utf-8");
|
|
57
|
+
if (defaultBranch !== "main") {
|
|
58
|
+
content = content.replaceAll("targeting('main')", `targeting('${defaultBranch}')`);
|
|
59
|
+
content = content.replaceAll("targeting the main branch", `targeting the ${defaultBranch} branch`);
|
|
60
|
+
}
|
|
61
|
+
await writeFile(path.join(kiciDir, "workflows", `${workflow}.ts`), content, "utf-8");
|
|
62
|
+
}
|
|
63
|
+
logger.info(pc.gray("Creating .kici/tests/"));
|
|
64
|
+
await mkdir(path.join(kiciDir, "tests"), { recursive: true });
|
|
65
|
+
logger.info(pc.gray("Writing .kici/tests/push-test.ts"));
|
|
66
|
+
const fixtureContent = generateSampleFixture(defaultBranch);
|
|
67
|
+
await writeFile(path.join(kiciDir, "tests", "push-test.ts"), fixtureContent, "utf-8");
|
|
68
|
+
logger.info(pc.green("Created sample test fixture at .kici/tests/push-test.ts"));
|
|
69
|
+
const kiciIgnorePath = path.resolve(".kiciignore");
|
|
70
|
+
if (!await checkExists(kiciIgnorePath)) {
|
|
71
|
+
logger.info(pc.gray("Writing .kiciignore"));
|
|
72
|
+
await writeFile(kiciIgnorePath, kiciIgnoreTemplate, "utf-8");
|
|
73
|
+
}
|
|
74
|
+
const devMode = options.useVerdaccioLocal || await detectDevelopmentMode();
|
|
75
|
+
logger.info(pc.gray("Writing .kici/package.json"));
|
|
76
|
+
const pkgContent = generatePackageJson(devMode);
|
|
77
|
+
await writeFile(path.join(kiciDir, "package.json"), pkgContent, "utf-8");
|
|
78
|
+
const useVerdaccio = devMode;
|
|
79
|
+
if (useVerdaccio) {
|
|
80
|
+
logger.info(pc.yellow("Pointing @kici-dev to local Verdaccio registry."));
|
|
81
|
+
const npmrc = "@kici-dev:registry=http://verdaccio.local:4873\n";
|
|
82
|
+
await writeFile(path.join(kiciDir, ".npmrc"), npmrc, "utf-8");
|
|
83
|
+
const rootNpmrc = path.resolve(".npmrc");
|
|
84
|
+
if (!await checkExists(rootNpmrc)) {
|
|
85
|
+
logger.info(pc.gray("Writing .npmrc (Verdaccio scope)"));
|
|
86
|
+
await writeFile(rootNpmrc, npmrc, "utf-8");
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (!options.mjs) {
|
|
90
|
+
logger.info(pc.gray("Writing .kici/tsconfig.json"));
|
|
91
|
+
const tsconfigContent = await generateTsConfig();
|
|
92
|
+
await writeFile(path.join(kiciDir, "tsconfig.json"), tsconfigContent, "utf-8");
|
|
93
|
+
await mkdir(path.join(kiciDir, "types"), { recursive: true });
|
|
94
|
+
logger.info(pc.gray("Created .kici/types/ for generated type declarations"));
|
|
95
|
+
if (!options.skipInstall) {
|
|
96
|
+
logger.info(pc.gray("Running npm install..."));
|
|
97
|
+
await $`cd ${kiciDir} && npm install`;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (options.privateRegistry) await writePrivateRegistryScaffold(kiciDir, {
|
|
101
|
+
url: options.privateRegistry,
|
|
102
|
+
scope: options.privateRegistryScope,
|
|
103
|
+
secretRef: options.privateRegistrySecret ?? "production:NPM_TOKEN"
|
|
104
|
+
});
|
|
105
|
+
if (await shouldWriteAgentsMd(options)) await writeAgentsMd(kiciDir);
|
|
106
|
+
logger.info(pc.gray("Updating .gitignore"));
|
|
107
|
+
await updateGitignore(useVerdaccio);
|
|
108
|
+
if (process.stdout.isTTY && process.env.CI !== "true") {
|
|
109
|
+
if (await findGitDir()) await offerHookInstallation(useVerdaccio);
|
|
110
|
+
}
|
|
111
|
+
logger.info(pc.green("\n✓ kici initialized successfully!\n"));
|
|
112
|
+
logger.info(pc.gray("Next steps:"));
|
|
113
|
+
logger.info(pc.gray(" 1. Edit workflows in .kici/workflows/"));
|
|
114
|
+
if (options.mjs || options.skipInstall) {
|
|
115
|
+
logger.info(pc.gray(" 2. Run npm install in .kici/ to generate a lockfile"));
|
|
116
|
+
logger.info(pc.gray(" 3. Test locally: kici test push"));
|
|
117
|
+
logger.info(pc.gray(" 4. Commit .kici/ to your repository\n"));
|
|
118
|
+
} else {
|
|
119
|
+
logger.info(pc.gray(" 2. Test locally: kici test push"));
|
|
120
|
+
logger.info(pc.gray(" 3. Commit .kici/ to your repository\n"));
|
|
121
|
+
}
|
|
122
|
+
return true;
|
|
123
|
+
} catch (error) {
|
|
124
|
+
const message = toErrorMessage(error);
|
|
125
|
+
logger.error(pc.red(`\nError: ${message}\n`));
|
|
126
|
+
if (process.env.KICI_DEBUG === "true" && error instanceof Error && error.stack) logger.error(pc.gray(error.stack));
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Check if a path exists
|
|
132
|
+
*
|
|
133
|
+
* @param targetPath - Path to check
|
|
134
|
+
* @returns true if exists, false otherwise
|
|
135
|
+
*/
|
|
136
|
+
async function checkExists(targetPath) {
|
|
137
|
+
try {
|
|
138
|
+
await access(targetPath);
|
|
139
|
+
return true;
|
|
140
|
+
} catch {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Select which workflows to include
|
|
146
|
+
*
|
|
147
|
+
* Interactive in TTY mode, defaults to all workflows in non-TTY/CI.
|
|
148
|
+
*
|
|
149
|
+
* @returns Array of workflow names to include
|
|
150
|
+
*/
|
|
151
|
+
async function selectWorkflows() {
|
|
152
|
+
if (!process.stdout.isTTY || process.env.CI === "true") return ["hello-world", "pr-checks"];
|
|
153
|
+
const selected = await checkbox({
|
|
154
|
+
message: "Which workflows would you like to include?",
|
|
155
|
+
choices: [{
|
|
156
|
+
name: "Hello World (minimal push example)",
|
|
157
|
+
value: "hello-world",
|
|
158
|
+
checked: true
|
|
159
|
+
}, {
|
|
160
|
+
name: "PR Checks (comprehensive PR workflow)",
|
|
161
|
+
value: "pr-checks",
|
|
162
|
+
checked: true
|
|
163
|
+
}]
|
|
164
|
+
});
|
|
165
|
+
if (selected.length === 0) return ["hello-world"];
|
|
166
|
+
return selected;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Detect the default branch of the current git repository.
|
|
170
|
+
*
|
|
171
|
+
* Tries in order:
|
|
172
|
+
* 1. git symbolic-ref refs/remotes/origin/HEAD (set after clone)
|
|
173
|
+
* 2. Current branch (HEAD)
|
|
174
|
+
* 3. Falls back to 'main'
|
|
175
|
+
*/
|
|
176
|
+
async function detectDefaultBranch() {
|
|
177
|
+
try {
|
|
178
|
+
const branch = (await $`git symbolic-ref refs/remotes/origin/HEAD`.quiet()).stdout.trim().replace("refs/remotes/origin/", "");
|
|
179
|
+
if (branch) return branch;
|
|
180
|
+
} catch {}
|
|
181
|
+
try {
|
|
182
|
+
const branch = (await $`git rev-parse --abbrev-ref HEAD`.quiet()).stdout.trim();
|
|
183
|
+
if (branch && branch !== "HEAD") return branch;
|
|
184
|
+
} catch {}
|
|
185
|
+
return "main";
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Detect if running in development mode
|
|
189
|
+
*
|
|
190
|
+
* Development mode uses workspace:* dependencies for local testing.
|
|
191
|
+
* Checks:
|
|
192
|
+
* 1. KICI_DEV environment variable
|
|
193
|
+
* 2. Root package.json kici.development flag
|
|
194
|
+
*
|
|
195
|
+
* @returns true if in development mode
|
|
196
|
+
*/
|
|
197
|
+
async function detectDevelopmentMode() {
|
|
198
|
+
if (process.env.KICI_DEV === "true") return true;
|
|
199
|
+
try {
|
|
200
|
+
const content = await readFile(path.resolve(process.cwd(), "package.json"), "utf-8");
|
|
201
|
+
return JSON.parse(content).kici?.development === true;
|
|
202
|
+
} catch {
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Generate tsconfig.json content with optional TypeScript path mappings.
|
|
208
|
+
*
|
|
209
|
+
* If sdkPath is configured in .kici/package.json, adds path mapping
|
|
210
|
+
* to enable IDE autocomplete from local SDK source.
|
|
211
|
+
*
|
|
212
|
+
* @returns tsconfig.json content as string
|
|
213
|
+
*/
|
|
214
|
+
async function generateTsConfig() {
|
|
215
|
+
const typeScriptPaths = await getTypeScriptPaths();
|
|
216
|
+
if (!typeScriptPaths) return tsconfigTemplate;
|
|
217
|
+
const baseConfig = JSON.parse(tsconfigTemplate);
|
|
218
|
+
baseConfig.compilerOptions.paths = typeScriptPaths;
|
|
219
|
+
return JSON.stringify(baseConfig, null, 2) + "\n";
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Update .gitignore with .kici/ entries
|
|
223
|
+
*
|
|
224
|
+
* Safely appends to .gitignore, checking for existing entries to avoid duplicates.
|
|
225
|
+
* Handles cases where .gitignore doesn't exist or already has broader patterns.
|
|
226
|
+
*
|
|
227
|
+
* @param useVerdaccio - When true, also adds .npmrc entries for .kici/ and root
|
|
228
|
+
*/
|
|
229
|
+
async function updateGitignore(useVerdaccio) {
|
|
230
|
+
const gitignorePath = path.resolve(".gitignore");
|
|
231
|
+
const entries = [".kici/node_modules/", ".kici/.secrets"];
|
|
232
|
+
if (useVerdaccio) entries.push(".kici/.npmrc", ".npmrc");
|
|
233
|
+
let content = "";
|
|
234
|
+
if (await checkExists(gitignorePath)) content = await readFile(gitignorePath, "utf-8");
|
|
235
|
+
const lines = content.split("\n");
|
|
236
|
+
if (lines.some((line) => {
|
|
237
|
+
const trimmed = line.trim();
|
|
238
|
+
return trimmed === ".kici/" || trimmed === ".kici/*";
|
|
239
|
+
})) return;
|
|
240
|
+
let newContent = content;
|
|
241
|
+
for (const entry of entries) if (!lines.some((line) => {
|
|
242
|
+
const trimmed = line.trim();
|
|
243
|
+
return trimmed === entry || trimmed === entry.replace(/\/$/, "");
|
|
244
|
+
})) newContent = newContent.endsWith("\n") || newContent === "" ? newContent + entry + "\n" : newContent + "\n" + entry + "\n";
|
|
245
|
+
await writeFile(gitignorePath, newContent, "utf-8");
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Scaffolds a private-registry example workflow + a `.kici/.npmrc.example`.
|
|
249
|
+
* Both files are inert by default — the customer wires them up after editing.
|
|
250
|
+
* Existing files are never overwritten.
|
|
251
|
+
*/
|
|
252
|
+
async function writePrivateRegistryScaffold(kiciDir, args) {
|
|
253
|
+
const scopeLine = args.scope ? `\n scope: '${args.scope}',` : "";
|
|
254
|
+
const npmrcScopeLine = args.scope ? `${args.scope}:registry=${args.url}\n` : `registry=${args.url}\n`;
|
|
255
|
+
const url = args.url.replace(/\/+$/, "");
|
|
256
|
+
const workflowExample = `// Example: workflow declaring a private npm registry.
|
|
257
|
+
// Copy or adapt into a real workflow under .kici/workflows/.
|
|
258
|
+
//
|
|
259
|
+
// The agent renders these into the .kici/.npmrc before running \`npm install\`.
|
|
260
|
+
// The token is resolved from the qualified secret reference at dispatch time
|
|
261
|
+
// (the orchestrator looks it up under the named environment's scoped secrets).
|
|
262
|
+
import { workflow, job, step } from '@kici-dev/sdk';
|
|
263
|
+
|
|
264
|
+
export default workflow('private-registry-example', {
|
|
265
|
+
registries: [
|
|
266
|
+
{
|
|
267
|
+
url: '${args.url}',${scopeLine}
|
|
268
|
+
tokenSecret: '${args.secretRef}',
|
|
269
|
+
},
|
|
270
|
+
],
|
|
271
|
+
jobs: [
|
|
272
|
+
job('build', {
|
|
273
|
+
runsOn: 'linux',
|
|
274
|
+
steps: [step('install', async () => { /* deps install with auth */ })],
|
|
275
|
+
}),
|
|
276
|
+
],
|
|
277
|
+
});
|
|
278
|
+
`;
|
|
279
|
+
const npmrcExample = `# Example .kici/.npmrc using the option C escape hatch.
|
|
280
|
+
# Customer commits this file (without secret values), declares
|
|
281
|
+
# \`installEnv: ['<env>:<NAME>']\` on the workflow to project the
|
|
282
|
+
# secret as an env var on the install subprocess, and npm's native
|
|
283
|
+
# \${VAR} substitution does the rest.
|
|
284
|
+
${npmrcScopeLine}//${url.replace(/^https?:\/\//, "")}/:_authToken=\${MY_NPM_TOKEN}
|
|
285
|
+
`;
|
|
286
|
+
const examplePath = path.join(kiciDir, "workflows", "private-registry-example.ts.example");
|
|
287
|
+
if (await checkExists(examplePath)) logger.info(pc.gray("Skipping .kici/workflows/private-registry-example.ts.example (already exists)"));
|
|
288
|
+
else {
|
|
289
|
+
logger.info(pc.gray("Writing .kici/workflows/private-registry-example.ts.example"));
|
|
290
|
+
await writeFile(examplePath, workflowExample, "utf-8");
|
|
291
|
+
}
|
|
292
|
+
const npmrcPath = path.join(kiciDir, ".npmrc.example");
|
|
293
|
+
if (await checkExists(npmrcPath)) logger.info(pc.gray("Skipping .kici/.npmrc.example (already exists)"));
|
|
294
|
+
else {
|
|
295
|
+
logger.info(pc.gray("Writing .kici/.npmrc.example"));
|
|
296
|
+
await writeFile(npmrcPath, npmrcExample, "utf-8");
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Generate sample test fixture content.
|
|
301
|
+
* Uses the detected default branch for realistic fixture configuration.
|
|
302
|
+
*/
|
|
303
|
+
function generateSampleFixture(defaultBranch) {
|
|
304
|
+
return `import { fixture, push } from '@kici-dev/sdk';
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Sample test fixture: push to ${defaultBranch} branch.
|
|
308
|
+
*
|
|
309
|
+
* Run with: kici run remote push-${defaultBranch}
|
|
310
|
+
* List all: kici run remote
|
|
311
|
+
*/
|
|
312
|
+
export const push${capitalize(defaultBranch)} = fixture('push-${defaultBranch}', {
|
|
313
|
+
event: push({ branches: ['${defaultBranch}'] }),
|
|
314
|
+
});
|
|
315
|
+
`;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Capitalize the first letter of a string.
|
|
319
|
+
*/
|
|
320
|
+
function capitalize(s) {
|
|
321
|
+
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
322
|
+
}
|
|
323
|
+
/** Default .kiciignore content */
|
|
324
|
+
const kiciIgnoreTemplate = `node_modules/
|
|
325
|
+
.git/
|
|
326
|
+
dist/
|
|
327
|
+
coverage/
|
|
328
|
+
*.log
|
|
329
|
+
`;
|
|
330
|
+
/**
|
|
331
|
+
* Decide whether to scaffold .kici/AGENTS.md. The flag wins; otherwise we
|
|
332
|
+
* prompt in TTY mode (default Y) and default to writing in CI / non-TTY.
|
|
333
|
+
*/
|
|
334
|
+
async function shouldWriteAgentsMd(options) {
|
|
335
|
+
if (options.noAgentsMd) return false;
|
|
336
|
+
if (!process.stdout.isTTY || process.env.CI === "true") return true;
|
|
337
|
+
return await confirm({
|
|
338
|
+
message: "Add LLM authoring context (.kici/AGENTS.md)?",
|
|
339
|
+
default: true
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Write the AGENTS.md template. Never overwrites an existing file — the
|
|
344
|
+
* customer may have hand-edited it for their project.
|
|
345
|
+
*/
|
|
346
|
+
async function writeAgentsMd(kiciDir) {
|
|
347
|
+
const target = path.join(kiciDir, "AGENTS.md");
|
|
348
|
+
if (await checkExists(target)) {
|
|
349
|
+
logger.info(pc.gray("Skipping .kici/AGENTS.md (already exists)"));
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
logger.info(pc.gray("Writing .kici/AGENTS.md"));
|
|
353
|
+
await writeFile(target, agentsMdTemplate, "utf-8");
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Offer to install pre-commit hook.
|
|
357
|
+
* Detects existing hook tools and prompts user.
|
|
358
|
+
*/
|
|
359
|
+
async function offerHookInstallation(useVerdaccio) {
|
|
360
|
+
const tools = await detectHookTools();
|
|
361
|
+
let selectedTool;
|
|
362
|
+
if (tools.length === 0) if (!await confirm({
|
|
363
|
+
message: "No pre-commit tool found. Install husky for git hooks?",
|
|
364
|
+
default: false
|
|
365
|
+
})) {
|
|
366
|
+
if (!await confirm({
|
|
367
|
+
message: "Add kici compile to .git/hooks/pre-commit instead?",
|
|
368
|
+
default: false
|
|
369
|
+
})) return;
|
|
370
|
+
selectedTool = "git";
|
|
371
|
+
} else selectedTool = "husky";
|
|
372
|
+
else if (tools.length === 1) {
|
|
373
|
+
if (!await confirm({
|
|
374
|
+
message: `Found ${tools[0].name}. Add kici compile hook?`,
|
|
375
|
+
default: true
|
|
376
|
+
})) return;
|
|
377
|
+
selectedTool = tools[0].name;
|
|
378
|
+
} else selectedTool = await select({
|
|
379
|
+
message: "Multiple pre-commit tools detected. Which would you like to use?",
|
|
380
|
+
choices: tools.map((t) => ({
|
|
381
|
+
name: t.name,
|
|
382
|
+
value: t.name
|
|
383
|
+
}))
|
|
384
|
+
});
|
|
385
|
+
const result = await installHook(selectedTool, { useVerdaccio });
|
|
386
|
+
if (result.success) if (result.action === "skipped") logger.info(pc.yellow(`Hook already installed: ${result.message}`));
|
|
387
|
+
else logger.info(pc.green(`Hook installed: ${result.message}`));
|
|
388
|
+
else logger.warn(pc.yellow(`Warning: ${result.message}`));
|
|
389
|
+
}
|
|
390
|
+
//#endregion
|
|
391
|
+
export { initCommand };
|
|
392
|
+
|
|
393
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface LoginOptions {
|
|
2
|
+
/** API key for non-interactive authentication */
|
|
3
|
+
token?: string;
|
|
4
|
+
/** Orchestrator URL for direct connection */
|
|
5
|
+
endpoint?: string;
|
|
6
|
+
/** Platform relay URL */
|
|
7
|
+
platformEndpoint?: string;
|
|
8
|
+
/** Routing key for webhook source identification */
|
|
9
|
+
routingKey?: string;
|
|
10
|
+
/** Force device authorization flow regardless of environment */
|
|
11
|
+
device?: boolean;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Authenticate with KiCI.
|
|
15
|
+
*
|
|
16
|
+
* - With `--token`, saves the API key directly (legacy flow)
|
|
17
|
+
* - Without `--token`, runs OAuth flow: PKCE (desktop) or device (headless)
|
|
18
|
+
* - With `--device`, forces device authorization flow
|
|
19
|
+
*
|
|
20
|
+
* Returns true on success, false on error.
|
|
21
|
+
*/
|
|
22
|
+
export declare function loginCommand(options: LoginOptions): Promise<boolean>;
|
|
23
|
+
//# sourceMappingURL=login.d.ts.map
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import "../chunk-gOLHoazu.js";
|
|
2
|
+
import { getConfigPath, mergeGlobalConfig } from "../remote/config.js";
|
|
3
|
+
import { deviceFlow, exchangeTokenForPat, pkceFlow } from "../remote/oauth.js";
|
|
4
|
+
import { isHeadless } from "../auth/headless-detect.js";
|
|
5
|
+
import pc from "picocolors";
|
|
6
|
+
import { toErrorMessage } from "@kici-dev/shared";
|
|
7
|
+
import os from "node:os";
|
|
8
|
+
import { createInterface } from "node:readline";
|
|
9
|
+
//#region src/commands/login.ts
|
|
10
|
+
/**
|
|
11
|
+
* Prompt the user for input via stdin.
|
|
12
|
+
* Returns the trimmed input string.
|
|
13
|
+
*/
|
|
14
|
+
async function promptInput(prompt) {
|
|
15
|
+
const rl = createInterface({
|
|
16
|
+
input: process.stdin,
|
|
17
|
+
output: process.stderr
|
|
18
|
+
});
|
|
19
|
+
return new Promise((resolve) => {
|
|
20
|
+
rl.question(prompt, (answer) => {
|
|
21
|
+
rl.close();
|
|
22
|
+
resolve(answer.trim());
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Check if a PAT is expiring within 7 days and print a warning.
|
|
28
|
+
*/
|
|
29
|
+
function checkPatExpiry(expiresAt) {
|
|
30
|
+
const expiryDate = new Date(expiresAt);
|
|
31
|
+
const now = /* @__PURE__ */ new Date();
|
|
32
|
+
const daysUntilExpiry = (expiryDate.getTime() - now.getTime()) / (1e3 * 60 * 60 * 24);
|
|
33
|
+
if (daysUntilExpiry <= 7 && daysUntilExpiry > 0) {
|
|
34
|
+
console.log(pc.yellow(`\n Warning: your personal access token expires in ${Math.ceil(daysUntilExpiry)} day(s) (${expiryDate.toLocaleDateString()}).`));
|
|
35
|
+
console.log(pc.yellow(" Run `kici login` again to refresh it."));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Run the OAuth authentication flow (PKCE or device flow).
|
|
40
|
+
*
|
|
41
|
+
* Steps:
|
|
42
|
+
* 1. Detect environment (headless vs desktop)
|
|
43
|
+
* 2. Run appropriate OAuth flow to get OIDC access token
|
|
44
|
+
* 3. Exchange OIDC token for a personal access token (PAT)
|
|
45
|
+
* 4. Save PAT to global config
|
|
46
|
+
*/
|
|
47
|
+
async function oauthLogin(options) {
|
|
48
|
+
const platformUrl = options.platformEndpoint || process.env.KICI_PLATFORM_URL || "";
|
|
49
|
+
const issuer = process.env.KICI_OIDC_ISSUER || "";
|
|
50
|
+
const clientId = process.env.KICI_OIDC_CLIENT_ID || "";
|
|
51
|
+
const projectId = process.env.KICI_OIDC_PROJECT_ID || "";
|
|
52
|
+
const missing = [];
|
|
53
|
+
if (!platformUrl) missing.push("KICI_PLATFORM_URL");
|
|
54
|
+
if (!issuer) missing.push("KICI_OIDC_ISSUER");
|
|
55
|
+
if (!clientId) missing.push("KICI_OIDC_CLIENT_ID");
|
|
56
|
+
if (missing.length > 0) {
|
|
57
|
+
console.error(pc.red(`Error: missing required env var(s) for OAuth login: ${missing.join(", ")}`));
|
|
58
|
+
console.error(pc.gray(" Set them to your Platform and Zitadel endpoints, for example:"));
|
|
59
|
+
console.error(pc.gray(" export KICI_PLATFORM_URL=https://your-platform.example.com"));
|
|
60
|
+
console.error(pc.gray(" export KICI_OIDC_ISSUER=https://your-zitadel.example.com"));
|
|
61
|
+
console.error(pc.gray(" export KICI_OIDC_CLIENT_ID=<cli-client-id>"));
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
console.log(pc.cyan("\n Step 1/4: Detecting environment..."));
|
|
65
|
+
const browserCmdSet = !!process.env.KICI_BROWSER_CMD;
|
|
66
|
+
const useDeviceFlow = options.device || !browserCmdSet && isHeadless();
|
|
67
|
+
const flowName = useDeviceFlow ? "device authorization" : "PKCE (browser)";
|
|
68
|
+
console.log(pc.gray(` Using ${flowName} flow`));
|
|
69
|
+
console.log(pc.cyan(`\n Step 2/4: Authenticating with ZITADEL (${flowName})...`));
|
|
70
|
+
let accessToken;
|
|
71
|
+
const oauthOpts = {
|
|
72
|
+
issuer,
|
|
73
|
+
clientId,
|
|
74
|
+
projectId: projectId || void 0
|
|
75
|
+
};
|
|
76
|
+
if (useDeviceFlow) accessToken = await deviceFlow(oauthOpts);
|
|
77
|
+
else accessToken = await pkceFlow(oauthOpts);
|
|
78
|
+
console.log(pc.cyan("\n Step 3/4: Exchanging token for personal access token..."));
|
|
79
|
+
const machineName = os.hostname();
|
|
80
|
+
const patResult = await exchangeTokenForPat({
|
|
81
|
+
platformUrl,
|
|
82
|
+
accessToken,
|
|
83
|
+
machineName
|
|
84
|
+
});
|
|
85
|
+
console.log(pc.cyan("\n Step 4/4: Saving credentials..."));
|
|
86
|
+
const configUpdate = {
|
|
87
|
+
pat: patResult.token,
|
|
88
|
+
patId: patResult.id,
|
|
89
|
+
patExpiresAt: patResult.expiresAt
|
|
90
|
+
};
|
|
91
|
+
if (options.endpoint) configUpdate.endpoint = options.endpoint;
|
|
92
|
+
if (options.platformEndpoint) configUpdate.platformEndpoint = options.platformEndpoint;
|
|
93
|
+
if (options.routingKey) configUpdate.routingKey = options.routingKey;
|
|
94
|
+
await mergeGlobalConfig(configUpdate);
|
|
95
|
+
const configPath = getConfigPath();
|
|
96
|
+
const expiryDate = new Date(patResult.expiresAt).toLocaleDateString();
|
|
97
|
+
console.log(pc.green(`\n Authenticated successfully!`));
|
|
98
|
+
console.log(pc.gray(` PAT expires: ${expiryDate}`));
|
|
99
|
+
console.log(pc.gray(` Config saved to ${configPath}`));
|
|
100
|
+
checkPatExpiry(patResult.expiresAt);
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Authenticate with KiCI.
|
|
105
|
+
*
|
|
106
|
+
* - With `--token`, saves the API key directly (legacy flow)
|
|
107
|
+
* - Without `--token`, runs OAuth flow: PKCE (desktop) or device (headless)
|
|
108
|
+
* - With `--device`, forces device authorization flow
|
|
109
|
+
*
|
|
110
|
+
* Returns true on success, false on error.
|
|
111
|
+
*/
|
|
112
|
+
async function loginCommand(options) {
|
|
113
|
+
try {
|
|
114
|
+
if (options.token !== void 0) return await legacyTokenLogin(options);
|
|
115
|
+
return await oauthLogin(options);
|
|
116
|
+
} catch (err) {
|
|
117
|
+
const message = toErrorMessage(err);
|
|
118
|
+
console.error(pc.red(`\n Login failed: ${message}`));
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Legacy login flow: saves an API key directly to config.
|
|
124
|
+
*/
|
|
125
|
+
async function legacyTokenLogin(options) {
|
|
126
|
+
let token = options.token;
|
|
127
|
+
if (token === void 0) token = await promptInput("Enter your KiCI API key: ");
|
|
128
|
+
if (!token || token.length === 0) {
|
|
129
|
+
console.error(pc.red("Error: API key cannot be empty"));
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
const update = { token };
|
|
133
|
+
if (options.endpoint) update.endpoint = options.endpoint;
|
|
134
|
+
if (options.platformEndpoint) update.platformEndpoint = options.platformEndpoint;
|
|
135
|
+
if (options.routingKey) update.routingKey = options.routingKey;
|
|
136
|
+
await mergeGlobalConfig(update);
|
|
137
|
+
const configPath = getConfigPath();
|
|
138
|
+
console.log(pc.green(`Authenticated successfully. Config saved to ${configPath}`));
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
//#endregion
|
|
142
|
+
export { loginCommand };
|
|
143
|
+
|
|
144
|
+
//# sourceMappingURL=login.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* kici logout command
|
|
3
|
+
*
|
|
4
|
+
* Revokes PAT server-side and clears local auth config.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Logout from KiCI.
|
|
8
|
+
*
|
|
9
|
+
* 1. Revokes the PAT server-side (DELETE /api/v1/pats/:id)
|
|
10
|
+
* 2. Clears auth fields from local config (preserves non-auth settings)
|
|
11
|
+
*
|
|
12
|
+
* If server revocation fails (network error), still clears local config
|
|
13
|
+
* with a warning that the PAT will expire automatically.
|
|
14
|
+
*
|
|
15
|
+
* @returns true on completion (always succeeds from user's perspective)
|
|
16
|
+
*/
|
|
17
|
+
export declare function logoutCommand(): Promise<boolean>;
|
|
18
|
+
//# sourceMappingURL=logout.d.ts.map
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import "../chunk-gOLHoazu.js";
|
|
2
|
+
import { getConfigPath, loadGlobalConfig, saveGlobalConfig } from "../remote/config.js";
|
|
3
|
+
import pc from "picocolors";
|
|
4
|
+
//#region src/commands/logout.ts
|
|
5
|
+
/**
|
|
6
|
+
* kici logout command
|
|
7
|
+
*
|
|
8
|
+
* Revokes PAT server-side and clears local auth config.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Logout from KiCI.
|
|
12
|
+
*
|
|
13
|
+
* 1. Revokes the PAT server-side (DELETE /api/v1/pats/:id)
|
|
14
|
+
* 2. Clears auth fields from local config (preserves non-auth settings)
|
|
15
|
+
*
|
|
16
|
+
* If server revocation fails (network error), still clears local config
|
|
17
|
+
* with a warning that the PAT will expire automatically.
|
|
18
|
+
*
|
|
19
|
+
* @returns true on completion (always succeeds from user's perspective)
|
|
20
|
+
*/
|
|
21
|
+
async function logoutCommand() {
|
|
22
|
+
const config = await loadGlobalConfig();
|
|
23
|
+
if (!config.pat && !config.token) {
|
|
24
|
+
console.log(pc.gray("Not logged in."));
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
if (config.patId && config.platformEndpoint) try {
|
|
28
|
+
const url = `${config.platformEndpoint}/api/v1/pats/${config.patId}`;
|
|
29
|
+
if ((await fetch(url, {
|
|
30
|
+
method: "DELETE",
|
|
31
|
+
headers: {
|
|
32
|
+
Authorization: `Bearer ${config.pat}`,
|
|
33
|
+
"Content-Type": "application/json"
|
|
34
|
+
}
|
|
35
|
+
})).ok) console.log(pc.green("PAT revoked on server."));
|
|
36
|
+
else console.log(pc.yellow("Warning: could not revoke PAT on server (will expire automatically)."));
|
|
37
|
+
} catch {
|
|
38
|
+
console.log(pc.yellow("Warning: could not revoke PAT on server (will expire automatically)."));
|
|
39
|
+
}
|
|
40
|
+
const cleanConfig = { ...config };
|
|
41
|
+
delete cleanConfig.pat;
|
|
42
|
+
delete cleanConfig.patId;
|
|
43
|
+
delete cleanConfig.patExpiresAt;
|
|
44
|
+
delete cleanConfig.userEmail;
|
|
45
|
+
delete cleanConfig.activeOrgId;
|
|
46
|
+
delete cleanConfig.token;
|
|
47
|
+
await saveGlobalConfig(cleanConfig);
|
|
48
|
+
const configPath = getConfigPath();
|
|
49
|
+
console.log(pc.green(`Logged out. Config cleared at ${configPath}.`));
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
//#endregion
|
|
53
|
+
export { logoutCommand };
|
|
54
|
+
|
|
55
|
+
//# sourceMappingURL=logout.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* kici org commands
|
|
3
|
+
*
|
|
4
|
+
* Org management: list, use, current.
|
|
5
|
+
* Uses PAT auth to fetch user's organizations from Platform API.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* List user's organizations.
|
|
9
|
+
*
|
|
10
|
+
* Fetches orgs from Platform API and displays them as a formatted table.
|
|
11
|
+
* Active org is marked with a star.
|
|
12
|
+
*/
|
|
13
|
+
export declare function orgListCommand(): Promise<boolean>;
|
|
14
|
+
/**
|
|
15
|
+
* Switch active organization.
|
|
16
|
+
*
|
|
17
|
+
* Matches by display name (case-insensitive) or ID.
|
|
18
|
+
* Validates org exists before setting.
|
|
19
|
+
*/
|
|
20
|
+
export declare function orgUseCommand(nameOrId: string): Promise<boolean>;
|
|
21
|
+
/**
|
|
22
|
+
* Display current active organization.
|
|
23
|
+
*
|
|
24
|
+
* If PAT is available, fetches org name for display.
|
|
25
|
+
*/
|
|
26
|
+
export declare function orgCurrentCommand(): Promise<boolean>;
|
|
27
|
+
//# sourceMappingURL=org.d.ts.map
|