@flydocs/cli 0.6.0-alpha.26 → 0.6.0-alpha.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +533 -428
- package/package.json +1 -1
- package/template/.flydocs/config.json +1 -1
- package/template/.flydocs/version +1 -1
- package/template/manifest.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -15,7 +15,7 @@ var CLI_VERSION, CLI_NAME, PACKAGE_NAME, POSTHOG_API_KEY;
|
|
|
15
15
|
var init_constants = __esm({
|
|
16
16
|
"src/lib/constants.ts"() {
|
|
17
17
|
"use strict";
|
|
18
|
-
CLI_VERSION = "0.6.0-alpha.
|
|
18
|
+
CLI_VERSION = "0.6.0-alpha.28";
|
|
19
19
|
CLI_NAME = "flydocs";
|
|
20
20
|
PACKAGE_NAME = "@flydocs/cli";
|
|
21
21
|
POSTHOG_API_KEY = "phc_v1MSJTQDFkMS90CBh3mxIz3v8bYCCnKU6v1ir6bz0Xn";
|
|
@@ -2928,12 +2928,14 @@ var init_global_config = __esm({
|
|
|
2928
2928
|
function resolveRelayUrl() {
|
|
2929
2929
|
return process.env.FLYDOCS_RELAY_URL?.replace(/\/$/, "") ?? DEFAULT_RELAY_URL;
|
|
2930
2930
|
}
|
|
2931
|
-
function headers(apiKey) {
|
|
2932
|
-
|
|
2931
|
+
function headers(apiKey, workspaceId) {
|
|
2932
|
+
const h = {
|
|
2933
2933
|
Authorization: `Bearer ${apiKey}`,
|
|
2934
2934
|
"Content-Type": "application/json",
|
|
2935
2935
|
Accept: "application/json"
|
|
2936
2936
|
};
|
|
2937
|
+
if (workspaceId) h["X-Workspace"] = workspaceId;
|
|
2938
|
+
return h;
|
|
2937
2939
|
}
|
|
2938
2940
|
async function fetchConfigV2(apiKey, options = {}) {
|
|
2939
2941
|
const baseUrl = resolveRelayUrl();
|
|
@@ -2941,7 +2943,7 @@ async function fetchConfigV2(apiKey, options = {}) {
|
|
|
2941
2943
|
if (options.includeContext) params.set("includeContext", "true");
|
|
2942
2944
|
const response = await fetch(`${baseUrl}/config/generate?${params}`, {
|
|
2943
2945
|
method: "GET",
|
|
2944
|
-
headers: headers(apiKey),
|
|
2946
|
+
headers: headers(apiKey, options.workspaceId),
|
|
2945
2947
|
signal: AbortSignal.timeout(3e4)
|
|
2946
2948
|
});
|
|
2947
2949
|
if (!response.ok) {
|
|
@@ -2954,11 +2956,11 @@ async function fetchConfigV2(apiKey, options = {}) {
|
|
|
2954
2956
|
}
|
|
2955
2957
|
return await response.json();
|
|
2956
2958
|
}
|
|
2957
|
-
async function fetchTemplates(apiKey, sinceVersion) {
|
|
2959
|
+
async function fetchTemplates(apiKey, sinceVersion, workspaceId) {
|
|
2958
2960
|
const baseUrl = resolveRelayUrl();
|
|
2959
2961
|
const response = await fetch(`${baseUrl}/templates?since=${sinceVersion}`, {
|
|
2960
2962
|
method: "GET",
|
|
2961
|
-
headers: headers(apiKey),
|
|
2963
|
+
headers: headers(apiKey, workspaceId),
|
|
2962
2964
|
signal: AbortSignal.timeout(15e3)
|
|
2963
2965
|
});
|
|
2964
2966
|
if (!response.ok) {
|
|
@@ -2987,33 +2989,250 @@ var init_relay_client = __esm({
|
|
|
2987
2989
|
}
|
|
2988
2990
|
});
|
|
2989
2991
|
|
|
2992
|
+
// src/commands/cleanup.ts
|
|
2993
|
+
var cleanup_exports = {};
|
|
2994
|
+
__export(cleanup_exports, {
|
|
2995
|
+
default: () => cleanup_default,
|
|
2996
|
+
executeCleanup: () => executeCleanup,
|
|
2997
|
+
scanArtifacts: () => scanArtifacts
|
|
2998
|
+
});
|
|
2999
|
+
import { defineCommand as defineCommand2 } from "citty";
|
|
3000
|
+
import pc7 from "picocolors";
|
|
3001
|
+
import { join as join18 } from "path";
|
|
3002
|
+
import { readFile as readFile13, writeFile as writeFile11, rm as rm4 } from "fs/promises";
|
|
3003
|
+
async function scanArtifacts(targetDir) {
|
|
3004
|
+
const actions = [];
|
|
3005
|
+
const localMePath = join18(targetDir, ".flydocs", "me.json");
|
|
3006
|
+
if (await pathExists(localMePath) && await pathExists(globalMePath())) {
|
|
3007
|
+
actions.push({
|
|
3008
|
+
description: "Remove .flydocs/me.json (migrated to ~/.flydocs/me.json)",
|
|
3009
|
+
path: localMePath,
|
|
3010
|
+
type: "file"
|
|
3011
|
+
});
|
|
3012
|
+
}
|
|
3013
|
+
const validationCachePath = join18(
|
|
3014
|
+
targetDir,
|
|
3015
|
+
".flydocs",
|
|
3016
|
+
"validation-cache.json"
|
|
3017
|
+
);
|
|
3018
|
+
if (await pathExists(validationCachePath)) {
|
|
3019
|
+
actions.push({
|
|
3020
|
+
description: "Remove .flydocs/validation-cache.json (replaced by configVersion)",
|
|
3021
|
+
path: validationCachePath,
|
|
3022
|
+
type: "file"
|
|
3023
|
+
});
|
|
3024
|
+
}
|
|
3025
|
+
const hasGlobalCreds = await pathExists(credentialsPath());
|
|
3026
|
+
for (const envFile of [".env", ".env.local"]) {
|
|
3027
|
+
const envPath = join18(targetDir, envFile);
|
|
3028
|
+
if (!await pathExists(envPath)) continue;
|
|
3029
|
+
const content = await readFile13(envPath, "utf-8");
|
|
3030
|
+
const lines = content.split("\n");
|
|
3031
|
+
for (const line of lines) {
|
|
3032
|
+
const trimmed = line.trim();
|
|
3033
|
+
if (hasGlobalCreds && trimmed.startsWith("FLYDOCS_API_KEY=")) {
|
|
3034
|
+
actions.push({
|
|
3035
|
+
description: `Remove FLYDOCS_API_KEY from ${envFile} (migrated to ~/.flydocs/credentials)`,
|
|
3036
|
+
path: envPath,
|
|
3037
|
+
type: "line"
|
|
3038
|
+
});
|
|
3039
|
+
}
|
|
3040
|
+
if (trimmed.startsWith("FLYDOCS_RELAY_URL=")) {
|
|
3041
|
+
actions.push({
|
|
3042
|
+
description: `Remove FLYDOCS_RELAY_URL from ${envFile}`,
|
|
3043
|
+
path: envPath,
|
|
3044
|
+
type: "line"
|
|
3045
|
+
});
|
|
3046
|
+
}
|
|
3047
|
+
}
|
|
3048
|
+
}
|
|
3049
|
+
try {
|
|
3050
|
+
const config = await readAnyConfig(targetDir);
|
|
3051
|
+
const rawContent = await readFile13(
|
|
3052
|
+
join18(targetDir, ".flydocs", "config.json"),
|
|
3053
|
+
"utf-8"
|
|
3054
|
+
);
|
|
3055
|
+
const raw = JSON.parse(rawContent);
|
|
3056
|
+
const ghostFields = ["provider", "statusMapping"];
|
|
3057
|
+
for (const field of ghostFields) {
|
|
3058
|
+
if (field in raw) {
|
|
3059
|
+
actions.push({
|
|
3060
|
+
description: `Remove ghost field "${field}" from config.json`,
|
|
3061
|
+
path: join18(targetDir, ".flydocs", "config.json"),
|
|
3062
|
+
type: "field"
|
|
3063
|
+
});
|
|
3064
|
+
}
|
|
3065
|
+
}
|
|
3066
|
+
if (isConfigV2(config)) {
|
|
3067
|
+
const v1OnlyFields = [
|
|
3068
|
+
"workspaceId",
|
|
3069
|
+
"issueLabels",
|
|
3070
|
+
"workspace",
|
|
3071
|
+
"onboardComplete",
|
|
3072
|
+
"sourceRepo",
|
|
3073
|
+
"designSystem",
|
|
3074
|
+
"aiLabor"
|
|
3075
|
+
];
|
|
3076
|
+
for (const field of v1OnlyFields) {
|
|
3077
|
+
if (field in raw) {
|
|
3078
|
+
actions.push({
|
|
3079
|
+
description: `Remove v1 field "${field}" from config.json (server-owned in v2)`,
|
|
3080
|
+
path: join18(targetDir, ".flydocs", "config.json"),
|
|
3081
|
+
type: "field"
|
|
3082
|
+
});
|
|
3083
|
+
}
|
|
3084
|
+
}
|
|
3085
|
+
}
|
|
3086
|
+
} catch {
|
|
3087
|
+
}
|
|
3088
|
+
return actions;
|
|
3089
|
+
}
|
|
3090
|
+
async function executeCleanup(targetDir, actions) {
|
|
3091
|
+
const fileRemovals = actions.filter((a) => a.type === "file");
|
|
3092
|
+
const lineRemovals = actions.filter((a) => a.type === "line");
|
|
3093
|
+
const fieldRemovals = actions.filter((a) => a.type === "field");
|
|
3094
|
+
for (const action of fileRemovals) {
|
|
3095
|
+
await rm4(action.path, { force: true });
|
|
3096
|
+
}
|
|
3097
|
+
const envFiles = /* @__PURE__ */ new Map();
|
|
3098
|
+
for (const action of lineRemovals) {
|
|
3099
|
+
if (!envFiles.has(action.path)) {
|
|
3100
|
+
const content = await readFile13(action.path, "utf-8");
|
|
3101
|
+
envFiles.set(action.path, content.split("\n"));
|
|
3102
|
+
}
|
|
3103
|
+
}
|
|
3104
|
+
for (const [envPath, lines] of envFiles) {
|
|
3105
|
+
const filtered = lines.filter((line) => {
|
|
3106
|
+
const trimmed = line.trim();
|
|
3107
|
+
return !trimmed.startsWith("FLYDOCS_API_KEY=") && !trimmed.startsWith("FLYDOCS_RELAY_URL=");
|
|
3108
|
+
});
|
|
3109
|
+
const hasContent = filtered.some(
|
|
3110
|
+
(l) => l.trim().length > 0 && !l.trim().startsWith("#")
|
|
3111
|
+
);
|
|
3112
|
+
if (!hasContent) {
|
|
3113
|
+
await rm4(envPath, { force: true });
|
|
3114
|
+
} else {
|
|
3115
|
+
await writeFile11(envPath, filtered.join("\n"), "utf-8");
|
|
3116
|
+
}
|
|
3117
|
+
}
|
|
3118
|
+
if (fieldRemovals.length > 0) {
|
|
3119
|
+
const configPath = join18(targetDir, ".flydocs", "config.json");
|
|
3120
|
+
const content = await readFile13(configPath, "utf-8");
|
|
3121
|
+
const config = JSON.parse(content);
|
|
3122
|
+
for (const action of fieldRemovals) {
|
|
3123
|
+
const match = action.description.match(/"(\w+)"/);
|
|
3124
|
+
if (match) {
|
|
3125
|
+
delete config[match[1]];
|
|
3126
|
+
}
|
|
3127
|
+
}
|
|
3128
|
+
await writeFile11(
|
|
3129
|
+
configPath,
|
|
3130
|
+
JSON.stringify(config, null, 2) + "\n",
|
|
3131
|
+
"utf-8"
|
|
3132
|
+
);
|
|
3133
|
+
}
|
|
3134
|
+
}
|
|
3135
|
+
var cleanup_default;
|
|
3136
|
+
var init_cleanup = __esm({
|
|
3137
|
+
"src/commands/cleanup.ts"() {
|
|
3138
|
+
"use strict";
|
|
3139
|
+
init_ui();
|
|
3140
|
+
init_fs_ops();
|
|
3141
|
+
init_config();
|
|
3142
|
+
init_types();
|
|
3143
|
+
init_global_config();
|
|
3144
|
+
cleanup_default = defineCommand2({
|
|
3145
|
+
meta: {
|
|
3146
|
+
name: "cleanup",
|
|
3147
|
+
description: "Remove legacy v1 artifacts after migration (dry-run by default)"
|
|
3148
|
+
},
|
|
3149
|
+
args: {
|
|
3150
|
+
confirm: {
|
|
3151
|
+
type: "boolean",
|
|
3152
|
+
description: "Actually remove artifacts (default: dry-run only)",
|
|
3153
|
+
default: false
|
|
3154
|
+
},
|
|
3155
|
+
path: {
|
|
3156
|
+
type: "string",
|
|
3157
|
+
description: "Path to project directory"
|
|
3158
|
+
}
|
|
3159
|
+
},
|
|
3160
|
+
async run({ args }) {
|
|
3161
|
+
const targetDir = args.path ?? process.cwd();
|
|
3162
|
+
console.log();
|
|
3163
|
+
console.log(` ${pc7.bold("FlyDocs Cleanup")}`);
|
|
3164
|
+
console.log();
|
|
3165
|
+
const hasConfig = await pathExists(
|
|
3166
|
+
join18(targetDir, ".flydocs", "config.json")
|
|
3167
|
+
);
|
|
3168
|
+
if (!hasConfig) {
|
|
3169
|
+
printError("No .flydocs/config.json found. Run flydocs init first.");
|
|
3170
|
+
process.exit(1);
|
|
3171
|
+
}
|
|
3172
|
+
const hasGlobalCreds = await pathExists(credentialsPath());
|
|
3173
|
+
if (!hasGlobalCreds) {
|
|
3174
|
+
printWarning(
|
|
3175
|
+
"No global credentials found. Run flydocs init to set up credentials before cleanup."
|
|
3176
|
+
);
|
|
3177
|
+
}
|
|
3178
|
+
const actions = await scanArtifacts(targetDir);
|
|
3179
|
+
if (actions.length === 0) {
|
|
3180
|
+
printStatus("No legacy artifacts found. Already clean.");
|
|
3181
|
+
console.log();
|
|
3182
|
+
return;
|
|
3183
|
+
}
|
|
3184
|
+
const mode = args.confirm ? "Removing" : "Would remove";
|
|
3185
|
+
printInfo(`${mode} ${actions.length} legacy artifact(s):`);
|
|
3186
|
+
console.log();
|
|
3187
|
+
for (const action of actions) {
|
|
3188
|
+
const icon = args.confirm ? pc7.red("-") : pc7.yellow("?");
|
|
3189
|
+
console.log(` ${icon} ${action.description}`);
|
|
3190
|
+
}
|
|
3191
|
+
console.log();
|
|
3192
|
+
if (!args.confirm) {
|
|
3193
|
+
printInfo(
|
|
3194
|
+
`Dry-run complete. Run ${pc7.cyan("flydocs cleanup --confirm")} to remove.`
|
|
3195
|
+
);
|
|
3196
|
+
console.log();
|
|
3197
|
+
return;
|
|
3198
|
+
}
|
|
3199
|
+
await executeCleanup(targetDir, actions);
|
|
3200
|
+
printCompletionBox("Cleanup Complete", [
|
|
3201
|
+
`${pc7.green("+")} Removed ${actions.length} legacy artifact(s)`
|
|
3202
|
+
]);
|
|
3203
|
+
console.log();
|
|
3204
|
+
}
|
|
3205
|
+
});
|
|
3206
|
+
}
|
|
3207
|
+
});
|
|
3208
|
+
|
|
2990
3209
|
// src/lib/workspace.ts
|
|
2991
|
-
import { readFile as
|
|
2992
|
-
import { join as
|
|
3210
|
+
import { readFile as readFile14, writeFile as writeFile12, readdir as readdir4, stat as stat2 } from "fs/promises";
|
|
3211
|
+
import { join as join19, dirname as dirname3, relative, resolve as resolve3 } from "path";
|
|
2993
3212
|
async function readWorkspaceFile(dir) {
|
|
2994
|
-
const filePath =
|
|
3213
|
+
const filePath = join19(dir, WORKSPACE_FILENAME);
|
|
2995
3214
|
if (!await pathExists(filePath)) return null;
|
|
2996
|
-
const content = await
|
|
3215
|
+
const content = await readFile14(filePath, "utf-8");
|
|
2997
3216
|
const parsed = JSON.parse(content);
|
|
2998
3217
|
validateWorkspaceFile(parsed);
|
|
2999
3218
|
return parsed;
|
|
3000
3219
|
}
|
|
3001
3220
|
async function writeWorkspaceFile(dir, workspace) {
|
|
3002
|
-
const filePath =
|
|
3221
|
+
const filePath = join19(dir, WORKSPACE_FILENAME);
|
|
3003
3222
|
const content = JSON.stringify(workspace, null, 2) + "\n";
|
|
3004
|
-
await
|
|
3223
|
+
await writeFile12(filePath, content, "utf-8");
|
|
3005
3224
|
}
|
|
3006
3225
|
async function detectSiblingRepos(parentDir) {
|
|
3007
3226
|
const repos = {};
|
|
3008
3227
|
const entries = await readdir4(parentDir);
|
|
3009
3228
|
for (const entry of entries) {
|
|
3010
3229
|
if (entry.startsWith(".")) continue;
|
|
3011
|
-
const entryPath =
|
|
3230
|
+
const entryPath = join19(parentDir, entry);
|
|
3012
3231
|
const entryStat = await stat2(entryPath).catch(() => null);
|
|
3013
3232
|
if (!entryStat?.isDirectory()) continue;
|
|
3014
|
-
const hasGit = await pathExists(
|
|
3233
|
+
const hasGit = await pathExists(join19(entryPath, ".git"));
|
|
3015
3234
|
const hasFlydocs = await pathExists(
|
|
3016
|
-
|
|
3235
|
+
join19(entryPath, ".flydocs", "config.json")
|
|
3017
3236
|
);
|
|
3018
3237
|
if (hasGit || hasFlydocs) {
|
|
3019
3238
|
repos[entry] = { path: `./${entry}` };
|
|
@@ -3028,10 +3247,10 @@ async function readSiblingDescriptors(workspaceDir, repos) {
|
|
|
3028
3247
|
const descriptors = [];
|
|
3029
3248
|
for (const [name, entry] of Object.entries(repos)) {
|
|
3030
3249
|
const repoDir = resolve3(workspaceDir, entry.path);
|
|
3031
|
-
const serviceJsonPath =
|
|
3250
|
+
const serviceJsonPath = join19(repoDir, "flydocs", "context", "service.json");
|
|
3032
3251
|
if (!await pathExists(serviceJsonPath)) continue;
|
|
3033
3252
|
try {
|
|
3034
|
-
const content = await
|
|
3253
|
+
const content = await readFile14(serviceJsonPath, "utf-8");
|
|
3035
3254
|
const descriptor = JSON.parse(content);
|
|
3036
3255
|
descriptors.push({ name, path: entry.path, descriptor });
|
|
3037
3256
|
} catch {
|
|
@@ -3139,16 +3358,18 @@ var init_exports = {};
|
|
|
3139
3358
|
__export(init_exports, {
|
|
3140
3359
|
default: () => init_default
|
|
3141
3360
|
});
|
|
3142
|
-
import { defineCommand as
|
|
3143
|
-
import { text as text2, confirm as confirm3, isCancel as isCancel4, cancel as cancel3 } from "@clack/prompts";
|
|
3144
|
-
import
|
|
3145
|
-
import { join as
|
|
3146
|
-
import { mkdir as mkdir9, writeFile as
|
|
3361
|
+
import { defineCommand as defineCommand3 } from "citty";
|
|
3362
|
+
import { text as text2, confirm as confirm3, select as select2, isCancel as isCancel4, cancel as cancel3 } from "@clack/prompts";
|
|
3363
|
+
import pc8 from "picocolors";
|
|
3364
|
+
import { join as join20 } from "path";
|
|
3365
|
+
import { mkdir as mkdir9, writeFile as writeFile13 } from "fs/promises";
|
|
3366
|
+
import { execFile } from "child_process";
|
|
3367
|
+
import { promisify } from "util";
|
|
3147
3368
|
async function resolveAndValidateKey(keyArg, targetDir) {
|
|
3148
3369
|
let resolved = await resolveApiKey(keyArg, targetDir);
|
|
3149
3370
|
if (!resolved) {
|
|
3150
3371
|
console.log(
|
|
3151
|
-
` ${
|
|
3372
|
+
` ${pc8.dim("Get your API key (fdk_...) from your FlyDocs dashboard")}`
|
|
3152
3373
|
);
|
|
3153
3374
|
console.log();
|
|
3154
3375
|
const keyInput = await text2({
|
|
@@ -3178,32 +3399,56 @@ async function resolveAndValidateKey(keyArg, targetDir) {
|
|
|
3178
3399
|
printError("Invalid API key. Check your key and try again.");
|
|
3179
3400
|
process.exit(1);
|
|
3180
3401
|
}
|
|
3181
|
-
printStatus(`Authenticated with ${
|
|
3402
|
+
printStatus(`Authenticated with ${pc8.bold(result.org)}`);
|
|
3182
3403
|
} catch {
|
|
3183
3404
|
printError(
|
|
3184
3405
|
"Could not reach FlyDocs API. Check your network and try again."
|
|
3185
3406
|
);
|
|
3186
3407
|
console.log(
|
|
3187
|
-
` ${
|
|
3408
|
+
` ${pc8.dim("flydocs init requires server access. For offline use, run flydocs install instead.")}`
|
|
3188
3409
|
);
|
|
3189
3410
|
process.exit(1);
|
|
3190
3411
|
}
|
|
3412
|
+
const workspaces = await fetchWorkspaces(apiKey);
|
|
3413
|
+
let workspaceId;
|
|
3414
|
+
if (workspaces.length === 0) {
|
|
3415
|
+
printError("No workspaces found. Create one at app.flydocs.ai first.");
|
|
3416
|
+
process.exit(1);
|
|
3417
|
+
} else if (workspaces.length === 1) {
|
|
3418
|
+
workspaceId = workspaces[0].id;
|
|
3419
|
+
printStatus(`Workspace: ${pc8.bold(workspaces[0].name)}`);
|
|
3420
|
+
} else {
|
|
3421
|
+
const choice = await select2({
|
|
3422
|
+
message: "Select workspace",
|
|
3423
|
+
options: workspaces.map((ws) => ({
|
|
3424
|
+
value: ws.id,
|
|
3425
|
+
label: ws.name
|
|
3426
|
+
}))
|
|
3427
|
+
});
|
|
3428
|
+
if (isCancel4(choice)) {
|
|
3429
|
+
cancel3("Init cancelled.");
|
|
3430
|
+
process.exit(0);
|
|
3431
|
+
}
|
|
3432
|
+
workspaceId = choice;
|
|
3433
|
+
}
|
|
3191
3434
|
await writeGlobalCredential({
|
|
3192
3435
|
apiKey,
|
|
3436
|
+
workspaceId,
|
|
3193
3437
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3194
3438
|
lastValidated: (/* @__PURE__ */ new Date()).toISOString()
|
|
3195
3439
|
});
|
|
3196
3440
|
await checkCredentialPermissions();
|
|
3197
|
-
return apiKey;
|
|
3441
|
+
return { apiKey, workspaceId };
|
|
3198
3442
|
}
|
|
3199
|
-
async function pullServerConfig(apiKey, targetDir) {
|
|
3443
|
+
async function pullServerConfig(apiKey, targetDir, workspaceId) {
|
|
3200
3444
|
printInfo("Pulling config from server...");
|
|
3201
3445
|
const isFirstInit = !await pathExists(
|
|
3202
|
-
|
|
3446
|
+
join20(targetDir, ".flydocs", "config.json")
|
|
3203
3447
|
);
|
|
3204
3448
|
try {
|
|
3205
3449
|
const response = await fetchConfigV2(apiKey, {
|
|
3206
|
-
includeContext: isFirstInit
|
|
3450
|
+
includeContext: isFirstInit,
|
|
3451
|
+
workspaceId
|
|
3207
3452
|
});
|
|
3208
3453
|
if (!response.valid) {
|
|
3209
3454
|
printError("Server returned invalid config. Contact support.");
|
|
@@ -3215,7 +3460,7 @@ async function pullServerConfig(apiKey, targetDir) {
|
|
|
3215
3460
|
printError(`Server error: ${err.message}`);
|
|
3216
3461
|
if (err.status === 401) {
|
|
3217
3462
|
console.log(
|
|
3218
|
-
` ${
|
|
3463
|
+
` ${pc8.dim("Your API key may be revoked. Run flydocs auth with a new key.")}`
|
|
3219
3464
|
);
|
|
3220
3465
|
}
|
|
3221
3466
|
} else {
|
|
@@ -3227,7 +3472,7 @@ async function pullServerConfig(apiKey, targetDir) {
|
|
|
3227
3472
|
async function initSingleRepo(targetDir, apiKey, serverResponse) {
|
|
3228
3473
|
const actions = [];
|
|
3229
3474
|
const skipped = [];
|
|
3230
|
-
await mkdir9(
|
|
3475
|
+
await mkdir9(join20(targetDir, ".flydocs"), { recursive: true });
|
|
3231
3476
|
const configWithHash = applyConfigHash(serverResponse.config);
|
|
3232
3477
|
await writeConfig(targetDir, configWithHash);
|
|
3233
3478
|
actions.push("Wrote .flydocs/config.json (from server)");
|
|
@@ -3240,18 +3485,18 @@ async function initSingleRepo(targetDir, apiKey, serverResponse) {
|
|
|
3240
3485
|
actions.push("Wrote ~/.flydocs/me.json");
|
|
3241
3486
|
}
|
|
3242
3487
|
if (serverResponse.context) {
|
|
3243
|
-
const contextDir =
|
|
3488
|
+
const contextDir = join20(targetDir, "flydocs", "context");
|
|
3244
3489
|
await mkdir9(contextDir, { recursive: true });
|
|
3245
|
-
const projectMdPath =
|
|
3490
|
+
const projectMdPath = join20(contextDir, "project.md");
|
|
3246
3491
|
if (!await pathExists(projectMdPath)) {
|
|
3247
|
-
await
|
|
3492
|
+
await writeFile13(projectMdPath, serverResponse.context.projectMd, "utf-8");
|
|
3248
3493
|
actions.push("Wrote flydocs/context/project.md");
|
|
3249
3494
|
} else {
|
|
3250
3495
|
skipped.push("flydocs/context/project.md (already exists)");
|
|
3251
3496
|
}
|
|
3252
|
-
const serviceJsonPath =
|
|
3497
|
+
const serviceJsonPath = join20(contextDir, "service.json");
|
|
3253
3498
|
if (serverResponse.context.serviceJson && !await pathExists(serviceJsonPath)) {
|
|
3254
|
-
await
|
|
3499
|
+
await writeFile13(
|
|
3255
3500
|
serviceJsonPath,
|
|
3256
3501
|
JSON.stringify(serverResponse.context.serviceJson, null, 2) + "\n",
|
|
3257
3502
|
"utf-8"
|
|
@@ -3264,10 +3509,44 @@ async function initSingleRepo(targetDir, apiKey, serverResponse) {
|
|
|
3264
3509
|
await ensureGitignore(targetDir);
|
|
3265
3510
|
await ensurePlatformIgnores(targetDir);
|
|
3266
3511
|
actions.push("Updated ignore files");
|
|
3512
|
+
const artifacts = await scanArtifacts(targetDir);
|
|
3513
|
+
if (artifacts.length > 0) {
|
|
3514
|
+
await executeCleanup(targetDir, artifacts);
|
|
3515
|
+
actions.push(`Cleaned ${artifacts.length} legacy artifact(s)`);
|
|
3516
|
+
}
|
|
3267
3517
|
return { actions, skipped };
|
|
3268
3518
|
}
|
|
3519
|
+
async function checkGitFreshness(repoDir) {
|
|
3520
|
+
const hasGit = await pathExists(join20(repoDir, ".git"));
|
|
3521
|
+
if (!hasGit) return;
|
|
3522
|
+
try {
|
|
3523
|
+
await execFileAsync("git", ["-C", repoDir, "fetch", "--quiet"], {
|
|
3524
|
+
timeout: 15e3
|
|
3525
|
+
});
|
|
3526
|
+
const { stdout } = await execFileAsync(
|
|
3527
|
+
"git",
|
|
3528
|
+
["-C", repoDir, "rev-list", "--count", "HEAD..@{upstream}"],
|
|
3529
|
+
{ timeout: 5e3 }
|
|
3530
|
+
);
|
|
3531
|
+
const behind = parseInt(stdout.trim(), 10);
|
|
3532
|
+
if (behind <= 0) return;
|
|
3533
|
+
printWarning(`Repo is ${behind} commit(s) behind remote.`);
|
|
3534
|
+
const shouldPull = await confirm3({
|
|
3535
|
+
message: "Pull latest before init?"
|
|
3536
|
+
});
|
|
3537
|
+
if (isCancel4(shouldPull) || !shouldPull) {
|
|
3538
|
+
printInfo("Continuing without pulling.");
|
|
3539
|
+
return;
|
|
3540
|
+
}
|
|
3541
|
+
await execFileAsync("git", ["-C", repoDir, "pull", "--ff-only"], {
|
|
3542
|
+
timeout: 3e4
|
|
3543
|
+
});
|
|
3544
|
+
printStatus("Pulled latest from remote.");
|
|
3545
|
+
} catch {
|
|
3546
|
+
}
|
|
3547
|
+
}
|
|
3269
3548
|
async function isParentDirectory(dir) {
|
|
3270
|
-
const hasGit = await pathExists(
|
|
3549
|
+
const hasGit = await pathExists(join20(dir, ".git"));
|
|
3271
3550
|
if (hasGit) return false;
|
|
3272
3551
|
const repos = await detectSiblingRepos(dir);
|
|
3273
3552
|
return Object.keys(repos).length >= 2;
|
|
@@ -3277,7 +3556,7 @@ async function runMultiRepoInit(parentDir, keyArg) {
|
|
|
3277
3556
|
const repoNames = Object.keys(repos).sort();
|
|
3278
3557
|
printInfo(`Detected ${repoNames.length} repos:`);
|
|
3279
3558
|
for (const name of repoNames) {
|
|
3280
|
-
console.log(` ${
|
|
3559
|
+
console.log(` ${pc8.cyan(name)}`);
|
|
3281
3560
|
}
|
|
3282
3561
|
console.log();
|
|
3283
3562
|
const shouldContinue = await confirm3({
|
|
@@ -3287,8 +3566,11 @@ async function runMultiRepoInit(parentDir, keyArg) {
|
|
|
3287
3566
|
cancel3("Init cancelled.");
|
|
3288
3567
|
process.exit(0);
|
|
3289
3568
|
}
|
|
3290
|
-
const firstRepoDir =
|
|
3291
|
-
const apiKey = await resolveAndValidateKey(
|
|
3569
|
+
const firstRepoDir = join20(parentDir, repoNames[0]);
|
|
3570
|
+
const { apiKey, workspaceId } = await resolveAndValidateKey(
|
|
3571
|
+
keyArg,
|
|
3572
|
+
firstRepoDir
|
|
3573
|
+
);
|
|
3292
3574
|
const allActions = [
|
|
3293
3575
|
"Stored credential globally (~/.flydocs/credentials)"
|
|
3294
3576
|
];
|
|
@@ -3296,10 +3578,11 @@ async function runMultiRepoInit(parentDir, keyArg) {
|
|
|
3296
3578
|
let allWarnings = [];
|
|
3297
3579
|
let firstResponse;
|
|
3298
3580
|
for (const repoName of repoNames) {
|
|
3299
|
-
const repoDir =
|
|
3581
|
+
const repoDir = join20(parentDir, repoName);
|
|
3300
3582
|
console.log();
|
|
3301
|
-
printInfo(`Initializing ${
|
|
3302
|
-
|
|
3583
|
+
printInfo(`Initializing ${pc8.bold(repoName)}...`);
|
|
3584
|
+
await checkGitFreshness(repoDir);
|
|
3585
|
+
const serverResponse = await pullServerConfig(apiKey, repoDir, workspaceId);
|
|
3303
3586
|
if (!firstResponse) firstResponse = serverResponse;
|
|
3304
3587
|
const { actions, skipped } = await initSingleRepo(
|
|
3305
3588
|
repoDir,
|
|
@@ -3327,47 +3610,60 @@ async function runMultiRepoInit(parentDir, keyArg) {
|
|
|
3327
3610
|
await writeWorkspaceFile(parentDir, workspaceFile);
|
|
3328
3611
|
allActions.push(`.flydocs-workspace.json (${repoNames.length} repos)`);
|
|
3329
3612
|
}
|
|
3330
|
-
const contextDir =
|
|
3331
|
-
const workspaceMdPath =
|
|
3613
|
+
const contextDir = join20(parentDir, "flydocs", "context");
|
|
3614
|
+
const workspaceMdPath = join20(contextDir, "workspace.md");
|
|
3332
3615
|
if (await pathExists(workspaceMdPath)) {
|
|
3333
3616
|
allSkipped.push("flydocs/context/workspace.md (already exists)");
|
|
3334
3617
|
} else {
|
|
3335
3618
|
await mkdir9(contextDir, { recursive: true });
|
|
3336
3619
|
const workspaceJson = await readWorkspaceFile(parentDir) ?? buildWorkspaceFile(firstResponse.workspaceId, repos);
|
|
3337
3620
|
const content = firstResponse.context?.workspaceMd ?? await generateWorkspaceMd(parentDir, workspaceJson);
|
|
3338
|
-
await
|
|
3621
|
+
await writeFile13(workspaceMdPath, content, "utf-8");
|
|
3339
3622
|
const source = firstResponse.context?.workspaceMd ? "from server" : "generated locally";
|
|
3340
3623
|
allActions.push(`Wrote flydocs/context/workspace.md (${source})`);
|
|
3341
3624
|
}
|
|
3342
3625
|
}
|
|
3343
3626
|
console.log();
|
|
3344
|
-
printInitReport(
|
|
3627
|
+
printInitReport(
|
|
3628
|
+
allActions,
|
|
3629
|
+
allSkipped,
|
|
3630
|
+
allWarnings,
|
|
3631
|
+
!!firstResponse?.context
|
|
3632
|
+
);
|
|
3345
3633
|
}
|
|
3346
|
-
function printInitReport(actions, skipped, warnings) {
|
|
3634
|
+
function printInitReport(actions, skipped, warnings, hasContext) {
|
|
3347
3635
|
console.log();
|
|
3348
3636
|
const lines = [];
|
|
3349
3637
|
for (const action of actions) {
|
|
3350
|
-
lines.push(`${
|
|
3638
|
+
lines.push(`${pc8.green("+")} ${action}`);
|
|
3351
3639
|
}
|
|
3352
3640
|
for (const skip of skipped) {
|
|
3353
|
-
lines.push(`${
|
|
3641
|
+
lines.push(`${pc8.dim("-")} ${skip}`);
|
|
3642
|
+
}
|
|
3643
|
+
if (!hasContext) {
|
|
3644
|
+
lines.push("");
|
|
3645
|
+
lines.push(
|
|
3646
|
+
`${pc8.yellow("!")} No generated context yet. An admin can generate it from the portal.`
|
|
3647
|
+
);
|
|
3354
3648
|
}
|
|
3355
3649
|
if (warnings.length > 0) {
|
|
3356
3650
|
lines.push("");
|
|
3357
3651
|
for (const warning of warnings) {
|
|
3358
|
-
lines.push(`${
|
|
3652
|
+
lines.push(`${pc8.yellow("!")} ${warning}`);
|
|
3359
3653
|
}
|
|
3360
3654
|
}
|
|
3361
3655
|
printCompletionBox("FlyDocs Initialized", lines);
|
|
3362
3656
|
console.log();
|
|
3363
3657
|
console.log(` Next steps:`);
|
|
3364
3658
|
console.log(
|
|
3365
|
-
` ${
|
|
3659
|
+
` ${pc8.cyan("flydocs sync")} Pull latest config and templates`
|
|
3660
|
+
);
|
|
3661
|
+
console.log(
|
|
3662
|
+
` ${pc8.cyan("cursor .")} ${pc8.dim("or")} ${pc8.cyan("code .")} Open your IDE, then use ${pc8.bold("/start-session")}`
|
|
3366
3663
|
);
|
|
3367
|
-
console.log(` ${pc7.cyan("/start-session")} \u2014 begin working`);
|
|
3368
3664
|
console.log();
|
|
3369
3665
|
}
|
|
3370
|
-
var init_default;
|
|
3666
|
+
var execFileAsync, init_default;
|
|
3371
3667
|
var init_init = __esm({
|
|
3372
3668
|
"src/commands/init.ts"() {
|
|
3373
3669
|
"use strict";
|
|
@@ -3379,8 +3675,10 @@ var init_init = __esm({
|
|
|
3379
3675
|
init_gitignore();
|
|
3380
3676
|
init_fs_ops();
|
|
3381
3677
|
init_relay_client();
|
|
3678
|
+
init_cleanup();
|
|
3382
3679
|
init_workspace();
|
|
3383
|
-
|
|
3680
|
+
execFileAsync = promisify(execFile);
|
|
3681
|
+
init_default = defineCommand3({
|
|
3384
3682
|
meta: {
|
|
3385
3683
|
name: "init",
|
|
3386
3684
|
description: "Initialize FlyDocs in this project (unified setup)"
|
|
@@ -3398,14 +3696,22 @@ var init_init = __esm({
|
|
|
3398
3696
|
async run({ args }) {
|
|
3399
3697
|
const targetDir = args.path ?? process.cwd();
|
|
3400
3698
|
console.log();
|
|
3401
|
-
console.log(` ${
|
|
3699
|
+
console.log(` ${pc8.bold("FlyDocs Init")}`);
|
|
3402
3700
|
console.log();
|
|
3403
3701
|
if (await isParentDirectory(targetDir)) {
|
|
3404
3702
|
await runMultiRepoInit(targetDir, args.key);
|
|
3405
3703
|
return;
|
|
3406
3704
|
}
|
|
3407
|
-
|
|
3408
|
-
const
|
|
3705
|
+
await checkGitFreshness(targetDir);
|
|
3706
|
+
const { apiKey, workspaceId } = await resolveAndValidateKey(
|
|
3707
|
+
args.key,
|
|
3708
|
+
targetDir
|
|
3709
|
+
);
|
|
3710
|
+
const serverResponse = await pullServerConfig(
|
|
3711
|
+
apiKey,
|
|
3712
|
+
targetDir,
|
|
3713
|
+
workspaceId
|
|
3714
|
+
);
|
|
3409
3715
|
const { actions, skipped } = await initSingleRepo(
|
|
3410
3716
|
targetDir,
|
|
3411
3717
|
apiKey,
|
|
@@ -3414,7 +3720,7 @@ var init_init = __esm({
|
|
|
3414
3720
|
actions.unshift("Stored credential globally (~/.flydocs/credentials)");
|
|
3415
3721
|
const topology = serverResponse.config.topology;
|
|
3416
3722
|
if (topology?.type === 4 && topology.label === "sibling-repos") {
|
|
3417
|
-
const parentDir =
|
|
3723
|
+
const parentDir = join20(targetDir, "..");
|
|
3418
3724
|
const existing = await readWorkspaceFile(parentDir);
|
|
3419
3725
|
if (existing) {
|
|
3420
3726
|
skipped.push(".flydocs-workspace.json (already exists)");
|
|
@@ -3432,7 +3738,12 @@ var init_init = __esm({
|
|
|
3432
3738
|
}
|
|
3433
3739
|
}
|
|
3434
3740
|
}
|
|
3435
|
-
printInitReport(
|
|
3741
|
+
printInitReport(
|
|
3742
|
+
actions,
|
|
3743
|
+
skipped,
|
|
3744
|
+
serverResponse.warnings,
|
|
3745
|
+
!!serverResponse.context
|
|
3746
|
+
);
|
|
3436
3747
|
}
|
|
3437
3748
|
});
|
|
3438
3749
|
}
|
|
@@ -3443,11 +3754,11 @@ var update_exports = {};
|
|
|
3443
3754
|
__export(update_exports, {
|
|
3444
3755
|
default: () => update_default
|
|
3445
3756
|
});
|
|
3446
|
-
import { defineCommand as
|
|
3447
|
-
import { resolve as resolve4, join as
|
|
3448
|
-
import { mkdir as mkdir10, cp as cp2, readFile as
|
|
3449
|
-
import { select as
|
|
3450
|
-
import
|
|
3757
|
+
import { defineCommand as defineCommand4 } from "citty";
|
|
3758
|
+
import { resolve as resolve4, join as join21 } from "path";
|
|
3759
|
+
import { mkdir as mkdir10, cp as cp2, readFile as readFile15, readdir as readdir5, rm as rm5 } from "fs/promises";
|
|
3760
|
+
import { select as select3, text as text3, confirm as confirm4, isCancel as isCancel5, cancel as cancel4 } from "@clack/prompts";
|
|
3761
|
+
import pc9 from "picocolors";
|
|
3451
3762
|
var update_default;
|
|
3452
3763
|
var init_update = __esm({
|
|
3453
3764
|
"src/commands/update.ts"() {
|
|
@@ -3466,7 +3777,7 @@ var init_update = __esm({
|
|
|
3466
3777
|
init_update_check();
|
|
3467
3778
|
init_telemetry();
|
|
3468
3779
|
init_integrity();
|
|
3469
|
-
update_default =
|
|
3780
|
+
update_default = defineCommand4({
|
|
3470
3781
|
meta: {
|
|
3471
3782
|
name: "update",
|
|
3472
3783
|
description: "Update an existing FlyDocs installation"
|
|
@@ -3515,7 +3826,7 @@ var init_update = __esm({
|
|
|
3515
3826
|
} else if (args.here) {
|
|
3516
3827
|
targetDir = process.cwd();
|
|
3517
3828
|
} else {
|
|
3518
|
-
const choice = await
|
|
3829
|
+
const choice = await select3({
|
|
3519
3830
|
message: "Which project would you like to update?",
|
|
3520
3831
|
options: [
|
|
3521
3832
|
{
|
|
@@ -3553,9 +3864,9 @@ var init_update = __esm({
|
|
|
3553
3864
|
}
|
|
3554
3865
|
targetDir = resolve4(targetDir);
|
|
3555
3866
|
process.chdir(targetDir);
|
|
3556
|
-
const hasVersion = await pathExists(
|
|
3867
|
+
const hasVersion = await pathExists(join21(targetDir, ".flydocs", "version"));
|
|
3557
3868
|
const hasConfig = await pathExists(
|
|
3558
|
-
|
|
3869
|
+
join21(targetDir, ".flydocs", "config.json")
|
|
3559
3870
|
);
|
|
3560
3871
|
if (!hasVersion && !hasConfig) {
|
|
3561
3872
|
printError(`Not a FlyDocs project: ${targetDir}`);
|
|
@@ -3566,8 +3877,8 @@ var init_update = __esm({
|
|
|
3566
3877
|
console.log();
|
|
3567
3878
|
let currentVersion = "0.1.0";
|
|
3568
3879
|
if (hasVersion) {
|
|
3569
|
-
const vContent = await
|
|
3570
|
-
|
|
3880
|
+
const vContent = await readFile15(
|
|
3881
|
+
join21(targetDir, ".flydocs", "version"),
|
|
3571
3882
|
"utf-8"
|
|
3572
3883
|
);
|
|
3573
3884
|
currentVersion = vContent.trim();
|
|
@@ -3601,10 +3912,10 @@ var init_update = __esm({
|
|
|
3601
3912
|
});
|
|
3602
3913
|
console.log(`Updating: v${currentVersion} \u2192 v${version}`);
|
|
3603
3914
|
console.log();
|
|
3604
|
-
const changelogPath =
|
|
3915
|
+
const changelogPath = join21(templateDir, "CHANGELOG.md");
|
|
3605
3916
|
const whatsNew = await getWhatsNew(changelogPath, currentVersion, version);
|
|
3606
3917
|
if (whatsNew.length > 0) {
|
|
3607
|
-
console.log(
|
|
3918
|
+
console.log(pc9.cyan("What's new:"));
|
|
3608
3919
|
console.log();
|
|
3609
3920
|
for (const entry of whatsNew) {
|
|
3610
3921
|
console.log(` ${entry}`);
|
|
@@ -3613,23 +3924,23 @@ var init_update = __esm({
|
|
|
3613
3924
|
}
|
|
3614
3925
|
const now = /* @__PURE__ */ new Date();
|
|
3615
3926
|
const ts = `${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, "0")}${String(now.getDate()).padStart(2, "0")}-${String(now.getHours()).padStart(2, "0")}${String(now.getMinutes()).padStart(2, "0")}${String(now.getSeconds()).padStart(2, "0")}`;
|
|
3616
|
-
const backupDir =
|
|
3927
|
+
const backupDir = join21(targetDir, ".flydocs", `backup-${ts}`);
|
|
3617
3928
|
await mkdir10(backupDir, { recursive: true });
|
|
3618
3929
|
if (hasConfig) {
|
|
3619
3930
|
await cp2(
|
|
3620
|
-
|
|
3621
|
-
|
|
3931
|
+
join21(targetDir, ".flydocs", "config.json"),
|
|
3932
|
+
join21(backupDir, "config.json")
|
|
3622
3933
|
);
|
|
3623
3934
|
printStatus(`Config backed up to .flydocs/backup-${ts}/`);
|
|
3624
3935
|
}
|
|
3625
3936
|
try {
|
|
3626
|
-
const flydocsDir =
|
|
3937
|
+
const flydocsDir = join21(targetDir, ".flydocs");
|
|
3627
3938
|
const entries = await readdir5(flydocsDir);
|
|
3628
3939
|
const backups = entries.filter((e) => e.startsWith("backup-")).sort();
|
|
3629
3940
|
if (backups.length > 3) {
|
|
3630
3941
|
const toRemove = backups.slice(0, backups.length - 3);
|
|
3631
3942
|
for (const old of toRemove) {
|
|
3632
|
-
await
|
|
3943
|
+
await rm5(join21(flydocsDir, old), { recursive: true, force: true });
|
|
3633
3944
|
}
|
|
3634
3945
|
}
|
|
3635
3946
|
} catch {
|
|
@@ -3668,17 +3979,17 @@ var init_update = __esm({
|
|
|
3668
3979
|
await ensureDirectories(targetDir, effectiveTier);
|
|
3669
3980
|
console.log("Replacing framework directories...");
|
|
3670
3981
|
await replaceDirectory(
|
|
3671
|
-
|
|
3672
|
-
|
|
3982
|
+
join21(templateDir, ".flydocs", "templates"),
|
|
3983
|
+
join21(targetDir, ".flydocs", "templates")
|
|
3673
3984
|
);
|
|
3674
3985
|
printStatus(".flydocs/templates");
|
|
3675
3986
|
await replaceDirectory(
|
|
3676
|
-
|
|
3677
|
-
|
|
3987
|
+
join21(templateDir, ".claude", "hooks"),
|
|
3988
|
+
join21(targetDir, ".claude", "hooks")
|
|
3678
3989
|
);
|
|
3679
3990
|
printStatus(".claude/hooks");
|
|
3680
3991
|
const hasExistingAgents = await pathExists(
|
|
3681
|
-
|
|
3992
|
+
join21(targetDir, ".claude", "agents")
|
|
3682
3993
|
);
|
|
3683
3994
|
let installAgents;
|
|
3684
3995
|
if (args.yes) {
|
|
@@ -3687,7 +3998,7 @@ var init_update = __esm({
|
|
|
3687
3998
|
installAgents = true;
|
|
3688
3999
|
} else {
|
|
3689
4000
|
console.log();
|
|
3690
|
-
console.log(` ${
|
|
4001
|
+
console.log(` ${pc9.bold(pc9.yellow("Sub-Agents (Recommended)"))}`);
|
|
3691
4002
|
console.log();
|
|
3692
4003
|
console.log(
|
|
3693
4004
|
" Sub-agents are specialized roles (PM, implementation, review,"
|
|
@@ -3710,20 +4021,20 @@ var init_update = __esm({
|
|
|
3710
4021
|
}
|
|
3711
4022
|
}
|
|
3712
4023
|
if (installAgents) {
|
|
3713
|
-
const claudeAgentsSrc =
|
|
4024
|
+
const claudeAgentsSrc = join21(templateDir, ".claude", "agents");
|
|
3714
4025
|
if (await pathExists(claudeAgentsSrc)) {
|
|
3715
|
-
await mkdir10(
|
|
4026
|
+
await mkdir10(join21(targetDir, ".claude", "agents"), { recursive: true });
|
|
3716
4027
|
await copyDirectoryContents(
|
|
3717
4028
|
claudeAgentsSrc,
|
|
3718
|
-
|
|
4029
|
+
join21(targetDir, ".claude", "agents")
|
|
3719
4030
|
);
|
|
3720
4031
|
}
|
|
3721
|
-
const cursorAgentsSrc =
|
|
4032
|
+
const cursorAgentsSrc = join21(templateDir, ".cursor", "agents");
|
|
3722
4033
|
if (await pathExists(cursorAgentsSrc)) {
|
|
3723
|
-
await mkdir10(
|
|
4034
|
+
await mkdir10(join21(targetDir, ".cursor", "agents"), { recursive: true });
|
|
3724
4035
|
await copyDirectoryContents(
|
|
3725
4036
|
cursorAgentsSrc,
|
|
3726
|
-
|
|
4037
|
+
join21(targetDir, ".cursor", "agents")
|
|
3727
4038
|
);
|
|
3728
4039
|
}
|
|
3729
4040
|
printStatus(
|
|
@@ -3737,47 +4048,47 @@ var init_update = __esm({
|
|
|
3737
4048
|
console.log();
|
|
3738
4049
|
console.log("Replacing framework files...");
|
|
3739
4050
|
await copyFile(
|
|
3740
|
-
|
|
3741
|
-
|
|
4051
|
+
join21(templateDir, ".claude", "CLAUDE.md"),
|
|
4052
|
+
join21(targetDir, ".claude", "CLAUDE.md")
|
|
3742
4053
|
);
|
|
3743
4054
|
await copyFile(
|
|
3744
|
-
|
|
3745
|
-
|
|
4055
|
+
join21(templateDir, ".claude", "settings.json"),
|
|
4056
|
+
join21(targetDir, ".claude", "settings.json")
|
|
3746
4057
|
);
|
|
3747
4058
|
printStatus(".claude/CLAUDE.md, settings.json");
|
|
3748
4059
|
await copyDirectoryContents(
|
|
3749
|
-
|
|
3750
|
-
|
|
4060
|
+
join21(templateDir, ".claude", "commands"),
|
|
4061
|
+
join21(targetDir, ".claude", "commands")
|
|
3751
4062
|
);
|
|
3752
4063
|
await copyDirectoryContents(
|
|
3753
|
-
|
|
3754
|
-
|
|
4064
|
+
join21(templateDir, ".claude", "commands"),
|
|
4065
|
+
join21(targetDir, ".cursor", "commands")
|
|
3755
4066
|
);
|
|
3756
4067
|
printStatus(".claude/commands, .cursor/commands");
|
|
3757
|
-
const skillsReadmeSrc =
|
|
4068
|
+
const skillsReadmeSrc = join21(templateDir, ".claude", "skills", "README.md");
|
|
3758
4069
|
if (await pathExists(skillsReadmeSrc)) {
|
|
3759
4070
|
await copyFile(
|
|
3760
4071
|
skillsReadmeSrc,
|
|
3761
|
-
|
|
4072
|
+
join21(targetDir, ".claude", "skills", "README.md")
|
|
3762
4073
|
);
|
|
3763
4074
|
}
|
|
3764
4075
|
printStatus(".claude/skills/README.md");
|
|
3765
4076
|
await copyFile(
|
|
3766
|
-
|
|
3767
|
-
|
|
4077
|
+
join21(templateDir, ".cursor", "hooks.json"),
|
|
4078
|
+
join21(targetDir, ".cursor", "hooks.json")
|
|
3768
4079
|
);
|
|
3769
4080
|
printStatus(".cursor/hooks.json");
|
|
3770
4081
|
await copyFile(
|
|
3771
|
-
|
|
3772
|
-
|
|
4082
|
+
join21(templateDir, "AGENTS.md"),
|
|
4083
|
+
join21(targetDir, "AGENTS.md")
|
|
3773
4084
|
);
|
|
3774
4085
|
printStatus("AGENTS.md");
|
|
3775
|
-
const envExampleSrc =
|
|
4086
|
+
const envExampleSrc = join21(templateDir, ".env.example");
|
|
3776
4087
|
if (await pathExists(envExampleSrc)) {
|
|
3777
|
-
await copyFile(envExampleSrc,
|
|
4088
|
+
await copyFile(envExampleSrc, join21(targetDir, ".env.example"));
|
|
3778
4089
|
printStatus(".env.example");
|
|
3779
4090
|
}
|
|
3780
|
-
const knowledgeTemplatesDir =
|
|
4091
|
+
const knowledgeTemplatesDir = join21(
|
|
3781
4092
|
targetDir,
|
|
3782
4093
|
"flydocs",
|
|
3783
4094
|
"knowledge",
|
|
@@ -3787,8 +4098,8 @@ var init_update = __esm({
|
|
|
3787
4098
|
await mkdir10(knowledgeTemplatesDir, { recursive: true });
|
|
3788
4099
|
}
|
|
3789
4100
|
for (const tmpl of ["decision.md", "feature.md", "note.md"]) {
|
|
3790
|
-
const src =
|
|
3791
|
-
const dest =
|
|
4101
|
+
const src = join21(templateDir, "flydocs", "knowledge", "templates", tmpl);
|
|
4102
|
+
const dest = join21(knowledgeTemplatesDir, tmpl);
|
|
3792
4103
|
if (await pathExists(src) && !await pathExists(dest)) {
|
|
3793
4104
|
await copyFile(src, dest);
|
|
3794
4105
|
}
|
|
@@ -3815,18 +4126,18 @@ var init_update = __esm({
|
|
|
3815
4126
|
printWarning("Config merge failed \u2014 config.json preserved as-is");
|
|
3816
4127
|
}
|
|
3817
4128
|
await copyFile(
|
|
3818
|
-
|
|
3819
|
-
|
|
4129
|
+
join21(templateDir, ".flydocs", "version"),
|
|
4130
|
+
join21(targetDir, ".flydocs", "version")
|
|
3820
4131
|
);
|
|
3821
4132
|
printStatus(`.flydocs/version \u2192 ${version}`);
|
|
3822
|
-
const clSrc =
|
|
4133
|
+
const clSrc = join21(templateDir, "CHANGELOG.md");
|
|
3823
4134
|
if (await pathExists(clSrc)) {
|
|
3824
|
-
await copyFile(clSrc,
|
|
4135
|
+
await copyFile(clSrc, join21(targetDir, ".flydocs", "CHANGELOG.md"));
|
|
3825
4136
|
printStatus(".flydocs/CHANGELOG.md");
|
|
3826
4137
|
}
|
|
3827
|
-
const mfSrc =
|
|
4138
|
+
const mfSrc = join21(templateDir, "manifest.json");
|
|
3828
4139
|
if (await pathExists(mfSrc)) {
|
|
3829
|
-
await copyFile(mfSrc,
|
|
4140
|
+
await copyFile(mfSrc, join21(targetDir, ".flydocs", "manifest.json"));
|
|
3830
4141
|
printStatus(".flydocs/manifest.json");
|
|
3831
4142
|
}
|
|
3832
4143
|
await generateIntegrity(targetDir, version);
|
|
@@ -3888,13 +4199,13 @@ var uninstall_exports = {};
|
|
|
3888
4199
|
__export(uninstall_exports, {
|
|
3889
4200
|
default: () => uninstall_default
|
|
3890
4201
|
});
|
|
3891
|
-
import { defineCommand as
|
|
3892
|
-
import { resolve as resolve5, join as
|
|
3893
|
-
import { readdir as readdir6, rm as
|
|
3894
|
-
import { confirm as confirm5, select as
|
|
3895
|
-
import
|
|
4202
|
+
import { defineCommand as defineCommand5 } from "citty";
|
|
4203
|
+
import { resolve as resolve5, join as join22 } from "path";
|
|
4204
|
+
import { readdir as readdir6, rm as rm6, rename as rename2 } from "fs/promises";
|
|
4205
|
+
import { confirm as confirm5, select as select4, isCancel as isCancel6, cancel as cancel5 } from "@clack/prompts";
|
|
4206
|
+
import pc10 from "picocolors";
|
|
3896
4207
|
async function removeOwnedSkills(targetDir) {
|
|
3897
|
-
const skillsDir =
|
|
4208
|
+
const skillsDir = join22(targetDir, ".claude", "skills");
|
|
3898
4209
|
const removed = [];
|
|
3899
4210
|
if (!await pathExists(skillsDir)) {
|
|
3900
4211
|
return removed;
|
|
@@ -3903,7 +4214,7 @@ async function removeOwnedSkills(targetDir) {
|
|
|
3903
4214
|
const entries = await readdir6(skillsDir);
|
|
3904
4215
|
for (const entry of entries) {
|
|
3905
4216
|
if (entry.startsWith(OWNED_SKILL_PREFIX)) {
|
|
3906
|
-
await
|
|
4217
|
+
await rm6(join22(skillsDir, entry), { recursive: true, force: true });
|
|
3907
4218
|
removed.push(`.claude/skills/${entry}`);
|
|
3908
4219
|
}
|
|
3909
4220
|
}
|
|
@@ -3912,7 +4223,7 @@ async function removeOwnedSkills(targetDir) {
|
|
|
3912
4223
|
return removed;
|
|
3913
4224
|
}
|
|
3914
4225
|
async function removeOwnedCursorRules(targetDir) {
|
|
3915
|
-
const rulesDir =
|
|
4226
|
+
const rulesDir = join22(targetDir, ".cursor", "rules");
|
|
3916
4227
|
const removed = [];
|
|
3917
4228
|
if (!await pathExists(rulesDir)) {
|
|
3918
4229
|
return removed;
|
|
@@ -3921,7 +4232,7 @@ async function removeOwnedCursorRules(targetDir) {
|
|
|
3921
4232
|
const entries = await readdir6(rulesDir);
|
|
3922
4233
|
for (const entry of entries) {
|
|
3923
4234
|
if (entry.startsWith(OWNED_RULE_PREFIX) && entry.endsWith(".mdc")) {
|
|
3924
|
-
await
|
|
4235
|
+
await rm6(join22(rulesDir, entry), { force: true });
|
|
3925
4236
|
removed.push(`.cursor/rules/${entry}`);
|
|
3926
4237
|
}
|
|
3927
4238
|
}
|
|
@@ -3940,9 +4251,9 @@ async function isEmptyDir(dirPath) {
|
|
|
3940
4251
|
async function cleanupEmptyParents(targetDir, dirs) {
|
|
3941
4252
|
const cleaned = [];
|
|
3942
4253
|
for (const dir of dirs) {
|
|
3943
|
-
const fullPath =
|
|
4254
|
+
const fullPath = join22(targetDir, dir);
|
|
3944
4255
|
if (await pathExists(fullPath) && await isEmptyDir(fullPath)) {
|
|
3945
|
-
await
|
|
4256
|
+
await rm6(fullPath, { recursive: true, force: true });
|
|
3946
4257
|
cleaned.push(dir);
|
|
3947
4258
|
}
|
|
3948
4259
|
}
|
|
@@ -3972,7 +4283,7 @@ var init_uninstall = __esm({
|
|
|
3972
4283
|
];
|
|
3973
4284
|
OWNED_SKILL_PREFIX = "flydocs-";
|
|
3974
4285
|
OWNED_RULE_PREFIX = "flydocs-";
|
|
3975
|
-
uninstall_default =
|
|
4286
|
+
uninstall_default = defineCommand5({
|
|
3976
4287
|
meta: {
|
|
3977
4288
|
name: "uninstall",
|
|
3978
4289
|
description: "Remove FlyDocs from a project directory"
|
|
@@ -4019,8 +4330,8 @@ var init_uninstall = __esm({
|
|
|
4019
4330
|
process.exit(1);
|
|
4020
4331
|
}
|
|
4021
4332
|
targetDir = resolve5(targetDir);
|
|
4022
|
-
const hasFlydocs = await pathExists(
|
|
4023
|
-
const hasAgentsMd = await pathExists(
|
|
4333
|
+
const hasFlydocs = await pathExists(join22(targetDir, ".flydocs"));
|
|
4334
|
+
const hasAgentsMd = await pathExists(join22(targetDir, "AGENTS.md"));
|
|
4024
4335
|
if (!hasFlydocs && !hasAgentsMd) {
|
|
4025
4336
|
printError(`Not a FlyDocs project: ${targetDir}`);
|
|
4026
4337
|
printInfo("No .flydocs/ directory or AGENTS.md found.");
|
|
@@ -4032,12 +4343,12 @@ var init_uninstall = __esm({
|
|
|
4032
4343
|
const removeAll = forceAll || args.all;
|
|
4033
4344
|
const skipPrompts = forceAll || args.yes;
|
|
4034
4345
|
let contentAction = "preserve";
|
|
4035
|
-
const hasUserContent = await pathExists(
|
|
4346
|
+
const hasUserContent = await pathExists(join22(targetDir, "flydocs"));
|
|
4036
4347
|
if (hasUserContent) {
|
|
4037
4348
|
if (removeAll) {
|
|
4038
4349
|
contentAction = "remove";
|
|
4039
4350
|
} else if (!skipPrompts) {
|
|
4040
|
-
const choice = await
|
|
4351
|
+
const choice = await select4({
|
|
4041
4352
|
message: "What should happen to your flydocs/ content (project docs, knowledge base)?",
|
|
4042
4353
|
options: [
|
|
4043
4354
|
{
|
|
@@ -4066,34 +4377,34 @@ var init_uninstall = __esm({
|
|
|
4066
4377
|
}
|
|
4067
4378
|
if (!skipPrompts) {
|
|
4068
4379
|
console.log();
|
|
4069
|
-
console.log(
|
|
4380
|
+
console.log(pc10.bold("The following will be removed:"));
|
|
4070
4381
|
console.log();
|
|
4071
4382
|
console.log(" Framework files:");
|
|
4072
4383
|
for (const [path] of ALWAYS_REMOVED) {
|
|
4073
|
-
console.log(` ${
|
|
4384
|
+
console.log(` ${pc10.dim(path)}`);
|
|
4074
4385
|
}
|
|
4075
|
-
console.log(` ${
|
|
4076
|
-
console.log(` ${
|
|
4386
|
+
console.log(` ${pc10.dim(".claude/skills/flydocs-*")}`);
|
|
4387
|
+
console.log(` ${pc10.dim(".cursor/rules/flydocs-*.mdc")}`);
|
|
4077
4388
|
if (hasUserContent) {
|
|
4078
4389
|
if (contentAction === "archive") {
|
|
4079
4390
|
console.log();
|
|
4080
4391
|
console.log(
|
|
4081
|
-
` User content: ${
|
|
4392
|
+
` User content: ${pc10.yellow("flydocs/ -> flydocs-archive/")}`
|
|
4082
4393
|
);
|
|
4083
4394
|
} else if (contentAction === "remove") {
|
|
4084
4395
|
console.log();
|
|
4085
|
-
console.log(` User content: ${
|
|
4396
|
+
console.log(` User content: ${pc10.red("flydocs/ (deleted)")}`);
|
|
4086
4397
|
} else {
|
|
4087
4398
|
console.log();
|
|
4088
|
-
console.log(` User content: ${
|
|
4399
|
+
console.log(` User content: ${pc10.green("flydocs/ (preserved)")}`);
|
|
4089
4400
|
}
|
|
4090
4401
|
}
|
|
4091
4402
|
console.log();
|
|
4092
|
-
console.log(
|
|
4403
|
+
console.log(pc10.bold("Preserved:"));
|
|
4093
4404
|
console.log(
|
|
4094
|
-
` ${
|
|
4405
|
+
` ${pc10.dim(".claude/skills/ (non-flydocs community skills)")}`
|
|
4095
4406
|
);
|
|
4096
|
-
console.log(` ${
|
|
4407
|
+
console.log(` ${pc10.dim(".env, .env.local")}`);
|
|
4097
4408
|
console.log();
|
|
4098
4409
|
const shouldContinue = await confirm5({
|
|
4099
4410
|
message: "Proceed with uninstall?"
|
|
@@ -4115,16 +4426,16 @@ var init_uninstall = __esm({
|
|
|
4115
4426
|
const removedRules = await removeOwnedCursorRules(targetDir);
|
|
4116
4427
|
result.removed.push(...removedRules);
|
|
4117
4428
|
for (const [relativePath, type] of ALWAYS_REMOVED) {
|
|
4118
|
-
const fullPath =
|
|
4429
|
+
const fullPath = join22(targetDir, relativePath);
|
|
4119
4430
|
if (!await pathExists(fullPath)) {
|
|
4120
4431
|
result.skipped.push(relativePath);
|
|
4121
4432
|
continue;
|
|
4122
4433
|
}
|
|
4123
4434
|
try {
|
|
4124
4435
|
if (type === "dir") {
|
|
4125
|
-
await
|
|
4436
|
+
await rm6(fullPath, { recursive: true, force: true });
|
|
4126
4437
|
} else {
|
|
4127
|
-
await
|
|
4438
|
+
await rm6(fullPath, { force: true });
|
|
4128
4439
|
}
|
|
4129
4440
|
result.removed.push(relativePath);
|
|
4130
4441
|
} catch {
|
|
@@ -4133,16 +4444,16 @@ var init_uninstall = __esm({
|
|
|
4133
4444
|
}
|
|
4134
4445
|
}
|
|
4135
4446
|
if (hasUserContent) {
|
|
4136
|
-
const flydocsPath =
|
|
4447
|
+
const flydocsPath = join22(targetDir, "flydocs");
|
|
4137
4448
|
if (contentAction === "archive") {
|
|
4138
|
-
const archivePath =
|
|
4449
|
+
const archivePath = join22(targetDir, "flydocs-archive");
|
|
4139
4450
|
if (await pathExists(archivePath)) {
|
|
4140
|
-
await
|
|
4451
|
+
await rm6(archivePath, { recursive: true, force: true });
|
|
4141
4452
|
}
|
|
4142
4453
|
await rename2(flydocsPath, archivePath);
|
|
4143
4454
|
result.archived.push("flydocs/ -> flydocs-archive/");
|
|
4144
4455
|
} else if (contentAction === "remove") {
|
|
4145
|
-
await
|
|
4456
|
+
await rm6(flydocsPath, { recursive: true, force: true });
|
|
4146
4457
|
result.removed.push("flydocs/");
|
|
4147
4458
|
}
|
|
4148
4459
|
}
|
|
@@ -4161,17 +4472,17 @@ var init_uninstall = __esm({
|
|
|
4161
4472
|
result.restored = originals.map((f) => f.relativePath);
|
|
4162
4473
|
}
|
|
4163
4474
|
console.log();
|
|
4164
|
-
console.log(
|
|
4475
|
+
console.log(pc10.bold("Uninstall Summary"));
|
|
4165
4476
|
console.log();
|
|
4166
4477
|
if (result.removed.length > 0) {
|
|
4167
|
-
console.log(` ${
|
|
4478
|
+
console.log(` ${pc10.green("Removed")} (${result.removed.length}):`);
|
|
4168
4479
|
for (const item of result.removed) {
|
|
4169
4480
|
printStatus(item);
|
|
4170
4481
|
}
|
|
4171
4482
|
}
|
|
4172
4483
|
if (result.archived.length > 0) {
|
|
4173
4484
|
console.log();
|
|
4174
|
-
console.log(` ${
|
|
4485
|
+
console.log(` ${pc10.yellow("Archived")} (${result.archived.length}):`);
|
|
4175
4486
|
for (const item of result.archived) {
|
|
4176
4487
|
printInfo(item);
|
|
4177
4488
|
}
|
|
@@ -4179,7 +4490,7 @@ var init_uninstall = __esm({
|
|
|
4179
4490
|
if (result.restored.length > 0) {
|
|
4180
4491
|
console.log();
|
|
4181
4492
|
console.log(
|
|
4182
|
-
` ${
|
|
4493
|
+
` ${pc10.green("Restored")} (${result.restored.length} pre-FlyDocs original(s)):`
|
|
4183
4494
|
);
|
|
4184
4495
|
for (const item of result.restored) {
|
|
4185
4496
|
printInfo(item);
|
|
@@ -4188,16 +4499,16 @@ var init_uninstall = __esm({
|
|
|
4188
4499
|
if (result.skipped.length > 0) {
|
|
4189
4500
|
console.log();
|
|
4190
4501
|
console.log(
|
|
4191
|
-
` ${
|
|
4502
|
+
` ${pc10.dim("Skipped")} (${result.skipped.length} \u2014 not found):`
|
|
4192
4503
|
);
|
|
4193
4504
|
for (const item of result.skipped) {
|
|
4194
|
-
console.log(` ${
|
|
4505
|
+
console.log(` ${pc10.dim(item)}`);
|
|
4195
4506
|
}
|
|
4196
4507
|
}
|
|
4197
4508
|
console.log();
|
|
4198
4509
|
printStatus("FlyDocs has been removed from this project.");
|
|
4199
4510
|
console.log();
|
|
4200
|
-
printInfo(`To reinstall: ${
|
|
4511
|
+
printInfo(`To reinstall: ${pc10.cyan("npx @flydocs/cli install --here")}`);
|
|
4201
4512
|
console.log();
|
|
4202
4513
|
}
|
|
4203
4514
|
});
|
|
@@ -4209,28 +4520,28 @@ var setup_exports = {};
|
|
|
4209
4520
|
__export(setup_exports, {
|
|
4210
4521
|
default: () => setup_default
|
|
4211
4522
|
});
|
|
4212
|
-
import { defineCommand as
|
|
4213
|
-
import
|
|
4523
|
+
import { defineCommand as defineCommand6 } from "citty";
|
|
4524
|
+
import pc11 from "picocolors";
|
|
4214
4525
|
var setup_default;
|
|
4215
4526
|
var init_setup = __esm({
|
|
4216
4527
|
"src/commands/setup.ts"() {
|
|
4217
4528
|
"use strict";
|
|
4218
|
-
setup_default =
|
|
4529
|
+
setup_default = defineCommand6({
|
|
4219
4530
|
meta: {
|
|
4220
4531
|
name: "setup",
|
|
4221
4532
|
description: "Configure FlyDocs settings for this project"
|
|
4222
4533
|
},
|
|
4223
4534
|
run() {
|
|
4224
4535
|
console.log();
|
|
4225
|
-
console.log(` ${
|
|
4536
|
+
console.log(` ${pc11.bold("FlyDocs Setup")}`);
|
|
4226
4537
|
console.log();
|
|
4227
4538
|
console.log(` Setup runs inside your IDE as an interactive AI command.`);
|
|
4228
4539
|
console.log();
|
|
4229
4540
|
console.log(
|
|
4230
|
-
` ${
|
|
4541
|
+
` ${pc11.cyan("Claude Code:")} Type ${pc11.bold("/flydocs-setup")} in chat`
|
|
4231
4542
|
);
|
|
4232
4543
|
console.log(
|
|
4233
|
-
` ${
|
|
4544
|
+
` ${pc11.cyan("Cursor:")} Type ${pc11.bold("/flydocs-setup")} in chat`
|
|
4234
4545
|
);
|
|
4235
4546
|
console.log();
|
|
4236
4547
|
console.log(` This configures your project context, detects your stack,`);
|
|
@@ -4246,14 +4557,14 @@ var skills_exports = {};
|
|
|
4246
4557
|
__export(skills_exports, {
|
|
4247
4558
|
default: () => skills_default
|
|
4248
4559
|
});
|
|
4249
|
-
import { defineCommand as
|
|
4250
|
-
import
|
|
4560
|
+
import { defineCommand as defineCommand7 } from "citty";
|
|
4561
|
+
import pc12 from "picocolors";
|
|
4251
4562
|
var list, search, add, remove, skills_default;
|
|
4252
4563
|
var init_skills2 = __esm({
|
|
4253
4564
|
"src/commands/skills.ts"() {
|
|
4254
4565
|
"use strict";
|
|
4255
4566
|
init_skill_manager();
|
|
4256
|
-
list =
|
|
4567
|
+
list = defineCommand7({
|
|
4257
4568
|
meta: {
|
|
4258
4569
|
name: "list",
|
|
4259
4570
|
description: "List installed skills"
|
|
@@ -4269,26 +4580,26 @@ var init_skills2 = __esm({
|
|
|
4269
4580
|
console.log(`${total} skill(s) installed:`);
|
|
4270
4581
|
if (result.platform.length > 0) {
|
|
4271
4582
|
console.log();
|
|
4272
|
-
console.log(
|
|
4583
|
+
console.log(pc12.bold("Platform"));
|
|
4273
4584
|
for (const skill of result.platform) {
|
|
4274
4585
|
console.log(
|
|
4275
|
-
` ${skill.name} ${
|
|
4586
|
+
` ${skill.name} ${pc12.dim(`(${skill.triggers} triggers)`)}`
|
|
4276
4587
|
);
|
|
4277
4588
|
}
|
|
4278
4589
|
}
|
|
4279
4590
|
if (result.community.length > 0) {
|
|
4280
4591
|
console.log();
|
|
4281
|
-
console.log(
|
|
4592
|
+
console.log(pc12.bold("Community"));
|
|
4282
4593
|
for (const skill of result.community) {
|
|
4283
4594
|
console.log(
|
|
4284
|
-
` ${skill.name} ${
|
|
4595
|
+
` ${skill.name} ${pc12.dim(`(${skill.triggers} triggers)`)}`
|
|
4285
4596
|
);
|
|
4286
4597
|
}
|
|
4287
4598
|
}
|
|
4288
4599
|
console.log();
|
|
4289
4600
|
}
|
|
4290
4601
|
});
|
|
4291
|
-
search =
|
|
4602
|
+
search = defineCommand7({
|
|
4292
4603
|
meta: {
|
|
4293
4604
|
name: "search",
|
|
4294
4605
|
description: "Search community skills"
|
|
@@ -4304,24 +4615,24 @@ var init_skills2 = __esm({
|
|
|
4304
4615
|
const results = await searchCatalog(args.keyword);
|
|
4305
4616
|
if (results.length === 0) {
|
|
4306
4617
|
console.log(`No skills found for "${args.keyword}".`);
|
|
4307
|
-
console.log(` Browse the catalog at: ${
|
|
4618
|
+
console.log(` Browse the catalog at: ${pc12.cyan("https://skills.sh/")}`);
|
|
4308
4619
|
return;
|
|
4309
4620
|
}
|
|
4310
4621
|
console.log();
|
|
4311
4622
|
console.log(`${results.length} skill(s) matching "${args.keyword}":`);
|
|
4312
4623
|
console.log();
|
|
4313
4624
|
for (const skill of results) {
|
|
4314
|
-
console.log(` ${
|
|
4625
|
+
console.log(` ${pc12.bold(skill.name)}`);
|
|
4315
4626
|
console.log(` ${skill.description}`);
|
|
4316
|
-
console.log(` ${
|
|
4627
|
+
console.log(` ${pc12.dim(skill.repo)}`);
|
|
4317
4628
|
if (skill.tags.length > 0) {
|
|
4318
|
-
console.log(` ${
|
|
4629
|
+
console.log(` ${pc12.dim(skill.tags.join(", "))}`);
|
|
4319
4630
|
}
|
|
4320
4631
|
console.log();
|
|
4321
4632
|
}
|
|
4322
4633
|
}
|
|
4323
4634
|
});
|
|
4324
|
-
add =
|
|
4635
|
+
add = defineCommand7({
|
|
4325
4636
|
meta: {
|
|
4326
4637
|
name: "add",
|
|
4327
4638
|
description: "Install a community skill"
|
|
@@ -4337,7 +4648,7 @@ var init_skills2 = __esm({
|
|
|
4337
4648
|
await addSkill(process.cwd(), args.source);
|
|
4338
4649
|
}
|
|
4339
4650
|
});
|
|
4340
|
-
remove =
|
|
4651
|
+
remove = defineCommand7({
|
|
4341
4652
|
meta: {
|
|
4342
4653
|
name: "remove",
|
|
4343
4654
|
description: "Remove an installed community skill"
|
|
@@ -4353,7 +4664,7 @@ var init_skills2 = __esm({
|
|
|
4353
4664
|
await removeSkill(process.cwd(), args.name);
|
|
4354
4665
|
}
|
|
4355
4666
|
});
|
|
4356
|
-
skills_default =
|
|
4667
|
+
skills_default = defineCommand7({
|
|
4357
4668
|
meta: {
|
|
4358
4669
|
name: "skills",
|
|
4359
4670
|
description: "Manage FlyDocs skills (list, search, add, remove)"
|
|
@@ -4373,10 +4684,10 @@ var connect_exports = {};
|
|
|
4373
4684
|
__export(connect_exports, {
|
|
4374
4685
|
default: () => connect_default
|
|
4375
4686
|
});
|
|
4376
|
-
import { defineCommand as
|
|
4687
|
+
import { defineCommand as defineCommand8 } from "citty";
|
|
4377
4688
|
import { text as text4, confirm as confirm6, isCancel as isCancel7, cancel as cancel6 } from "@clack/prompts";
|
|
4378
|
-
import
|
|
4379
|
-
import { join as
|
|
4689
|
+
import pc13 from "picocolors";
|
|
4690
|
+
import { join as join23 } from "path";
|
|
4380
4691
|
var connect_default;
|
|
4381
4692
|
var init_connect = __esm({
|
|
4382
4693
|
"src/commands/connect.ts"() {
|
|
@@ -4386,7 +4697,7 @@ var init_connect = __esm({
|
|
|
4386
4697
|
init_template();
|
|
4387
4698
|
init_ui();
|
|
4388
4699
|
init_api_key();
|
|
4389
|
-
connect_default =
|
|
4700
|
+
connect_default = defineCommand8({
|
|
4390
4701
|
meta: {
|
|
4391
4702
|
name: "connect",
|
|
4392
4703
|
description: "Connect FlyDocs to a cloud provider"
|
|
@@ -4411,11 +4722,11 @@ var init_connect = __esm({
|
|
|
4411
4722
|
},
|
|
4412
4723
|
async run({ args }) {
|
|
4413
4724
|
const targetDir = args.path ?? process.cwd();
|
|
4414
|
-
const configPath =
|
|
4725
|
+
const configPath = join23(targetDir, ".flydocs", "config.json");
|
|
4415
4726
|
if (!await pathExists(configPath)) {
|
|
4416
4727
|
printError("Not a FlyDocs project (.flydocs/config.json not found).");
|
|
4417
4728
|
console.log(
|
|
4418
|
-
` Run ${
|
|
4729
|
+
` Run ${pc13.cyan("flydocs")} first to install FlyDocs in this project.`
|
|
4419
4730
|
);
|
|
4420
4731
|
process.exit(1);
|
|
4421
4732
|
}
|
|
@@ -4432,10 +4743,10 @@ var init_connect = __esm({
|
|
|
4432
4743
|
}
|
|
4433
4744
|
}
|
|
4434
4745
|
console.log();
|
|
4435
|
-
console.log(` ${
|
|
4746
|
+
console.log(` ${pc13.bold("Connect to FlyDocs Cloud")}`);
|
|
4436
4747
|
console.log();
|
|
4437
4748
|
console.log(
|
|
4438
|
-
` ${
|
|
4749
|
+
` ${pc13.dim("Get your API key (fdk_...) from your FlyDocs dashboard")}`
|
|
4439
4750
|
);
|
|
4440
4751
|
console.log();
|
|
4441
4752
|
let apiKey = args.key ?? "";
|
|
@@ -4473,7 +4784,7 @@ var init_connect = __esm({
|
|
|
4473
4784
|
console.log(` Check your key and try again.`);
|
|
4474
4785
|
process.exit(1);
|
|
4475
4786
|
}
|
|
4476
|
-
printStatus(`Connected to ${
|
|
4787
|
+
printStatus(`Connected to ${pc13.bold(result.org)}`);
|
|
4477
4788
|
} catch {
|
|
4478
4789
|
printError(
|
|
4479
4790
|
"Could not reach relay API. Check your network and try again."
|
|
@@ -4481,7 +4792,7 @@ var init_connect = __esm({
|
|
|
4481
4792
|
process.exit(1);
|
|
4482
4793
|
}
|
|
4483
4794
|
const envFile = await storeEnvKey(targetDir, "FLYDOCS_API_KEY", apiKey);
|
|
4484
|
-
printStatus(`API key stored in ${
|
|
4795
|
+
printStatus(`API key stored in ${pc13.dim(envFile)}`);
|
|
4485
4796
|
} else {
|
|
4486
4797
|
try {
|
|
4487
4798
|
const result = await validateLinearKey(apiKey);
|
|
@@ -4491,7 +4802,7 @@ var init_connect = __esm({
|
|
|
4491
4802
|
process.exit(1);
|
|
4492
4803
|
}
|
|
4493
4804
|
printStatus(
|
|
4494
|
-
`Authenticated as ${
|
|
4805
|
+
`Authenticated as ${pc13.bold(result.name)} (${result.email})`
|
|
4495
4806
|
);
|
|
4496
4807
|
} catch {
|
|
4497
4808
|
printError("Invalid API key or network error.");
|
|
@@ -4499,7 +4810,7 @@ var init_connect = __esm({
|
|
|
4499
4810
|
process.exit(1);
|
|
4500
4811
|
}
|
|
4501
4812
|
const envFile = await storeEnvKey(targetDir, "LINEAR_API_KEY", apiKey);
|
|
4502
|
-
printStatus(`API key stored in ${
|
|
4813
|
+
printStatus(`API key stored in ${pc13.dim(envFile)}`);
|
|
4503
4814
|
}
|
|
4504
4815
|
const wasLocal = config.tier === "local";
|
|
4505
4816
|
config.tier = "cloud";
|
|
@@ -4515,14 +4826,14 @@ var init_connect = __esm({
|
|
|
4515
4826
|
}
|
|
4516
4827
|
console.log();
|
|
4517
4828
|
console.log(
|
|
4518
|
-
` ${
|
|
4829
|
+
` ${pc13.bold("Connected!")} Your project is now on the cloud tier.`
|
|
4519
4830
|
);
|
|
4520
4831
|
console.log();
|
|
4521
4832
|
console.log(` Next steps:`);
|
|
4522
4833
|
console.log(
|
|
4523
|
-
` 1. Run ${
|
|
4834
|
+
` 1. Run ${pc13.cyan("/flydocs-setup")} in your IDE to configure your project`
|
|
4524
4835
|
);
|
|
4525
|
-
console.log(` 2. Run ${
|
|
4836
|
+
console.log(` 2. Run ${pc13.cyan("/start-session")} to begin working`);
|
|
4526
4837
|
console.log();
|
|
4527
4838
|
}
|
|
4528
4839
|
});
|
|
@@ -4534,9 +4845,9 @@ var auth_exports = {};
|
|
|
4534
4845
|
__export(auth_exports, {
|
|
4535
4846
|
default: () => auth_default
|
|
4536
4847
|
});
|
|
4537
|
-
import { defineCommand as
|
|
4848
|
+
import { defineCommand as defineCommand9 } from "citty";
|
|
4538
4849
|
import { text as text5, confirm as confirm7, isCancel as isCancel8, cancel as cancel7 } from "@clack/prompts";
|
|
4539
|
-
import
|
|
4850
|
+
import pc14 from "picocolors";
|
|
4540
4851
|
var auth_default;
|
|
4541
4852
|
var init_auth = __esm({
|
|
4542
4853
|
"src/commands/auth.ts"() {
|
|
@@ -4544,7 +4855,7 @@ var init_auth = __esm({
|
|
|
4544
4855
|
init_ui();
|
|
4545
4856
|
init_api_key();
|
|
4546
4857
|
init_global_config();
|
|
4547
|
-
auth_default =
|
|
4858
|
+
auth_default = defineCommand9({
|
|
4548
4859
|
meta: {
|
|
4549
4860
|
name: "auth",
|
|
4550
4861
|
description: "Store API key globally (~/.flydocs/credentials)"
|
|
@@ -4558,13 +4869,13 @@ var init_auth = __esm({
|
|
|
4558
4869
|
},
|
|
4559
4870
|
async run({ args }) {
|
|
4560
4871
|
console.log();
|
|
4561
|
-
console.log(` ${
|
|
4872
|
+
console.log(` ${pc14.bold("FlyDocs Authentication")}`);
|
|
4562
4873
|
console.log();
|
|
4563
4874
|
let apiKey = args.key ?? "";
|
|
4564
4875
|
const existing = await readGlobalCredential();
|
|
4565
4876
|
if (existing?.apiKey && !apiKey) {
|
|
4566
4877
|
printInfo(
|
|
4567
|
-
`Existing key found: ${
|
|
4878
|
+
`Existing key found: ${pc14.dim(existing.apiKey.slice(0, 8) + "...")}`
|
|
4568
4879
|
);
|
|
4569
4880
|
const replace = await confirm7({
|
|
4570
4881
|
message: "Replace with a new key?"
|
|
@@ -4576,7 +4887,7 @@ var init_auth = __esm({
|
|
|
4576
4887
|
}
|
|
4577
4888
|
if (!apiKey) {
|
|
4578
4889
|
console.log(
|
|
4579
|
-
` ${
|
|
4890
|
+
` ${pc14.dim("Get your API key (fdk_...) from your FlyDocs dashboard")}`
|
|
4580
4891
|
);
|
|
4581
4892
|
console.log();
|
|
4582
4893
|
const keyInput = await text5({
|
|
@@ -4612,7 +4923,7 @@ var init_auth = __esm({
|
|
|
4612
4923
|
printError("Invalid API key. Check your key and try again.");
|
|
4613
4924
|
process.exit(1);
|
|
4614
4925
|
}
|
|
4615
|
-
printStatus(`Authenticated with ${
|
|
4926
|
+
printStatus(`Authenticated with ${pc14.bold(result.org)}`);
|
|
4616
4927
|
} catch {
|
|
4617
4928
|
printError(
|
|
4618
4929
|
"Could not reach FlyDocs API. Check your network and try again."
|
|
@@ -4627,10 +4938,10 @@ var init_auth = __esm({
|
|
|
4627
4938
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4628
4939
|
lastValidated: (/* @__PURE__ */ new Date()).toISOString()
|
|
4629
4940
|
});
|
|
4630
|
-
printStatus(`Key stored at ${
|
|
4941
|
+
printStatus(`Key stored at ${pc14.dim(credentialsPath())}`);
|
|
4631
4942
|
await checkCredentialPermissions();
|
|
4632
4943
|
console.log();
|
|
4633
|
-
console.log(` ${
|
|
4944
|
+
console.log(` ${pc14.bold("Authenticated!")} Key stored globally.`);
|
|
4634
4945
|
console.log(` All FlyDocs projects on this machine will use this key.`);
|
|
4635
4946
|
console.log();
|
|
4636
4947
|
}
|
|
@@ -4643,10 +4954,10 @@ var sync_exports = {};
|
|
|
4643
4954
|
__export(sync_exports, {
|
|
4644
4955
|
default: () => sync_default
|
|
4645
4956
|
});
|
|
4646
|
-
import { defineCommand as
|
|
4647
|
-
import
|
|
4648
|
-
import { join as
|
|
4649
|
-
import { mkdir as mkdir11, writeFile as
|
|
4957
|
+
import { defineCommand as defineCommand10 } from "citty";
|
|
4958
|
+
import pc15 from "picocolors";
|
|
4959
|
+
import { join as join24 } from "path";
|
|
4960
|
+
import { mkdir as mkdir11, writeFile as writeFile14 } from "fs/promises";
|
|
4650
4961
|
var sync_default;
|
|
4651
4962
|
var init_sync = __esm({
|
|
4652
4963
|
"src/commands/sync.ts"() {
|
|
@@ -4658,7 +4969,7 @@ var init_sync = __esm({
|
|
|
4658
4969
|
init_fs_ops();
|
|
4659
4970
|
init_types();
|
|
4660
4971
|
init_relay_client();
|
|
4661
|
-
sync_default =
|
|
4972
|
+
sync_default = defineCommand10({
|
|
4662
4973
|
meta: {
|
|
4663
4974
|
name: "sync",
|
|
4664
4975
|
description: "Pull latest config and templates from server"
|
|
@@ -4682,6 +4993,14 @@ var init_sync = __esm({
|
|
|
4682
4993
|
process.exit(1);
|
|
4683
4994
|
}
|
|
4684
4995
|
const apiKey = resolved.key;
|
|
4996
|
+
const cred = await readGlobalCredential();
|
|
4997
|
+
const workspaceId = cred?.workspaceId;
|
|
4998
|
+
if (!workspaceId) {
|
|
4999
|
+
printError(
|
|
5000
|
+
"No workspace ID found. Run `flydocs init` to set up your workspace."
|
|
5001
|
+
);
|
|
5002
|
+
process.exit(1);
|
|
5003
|
+
}
|
|
4685
5004
|
let currentTemplateVersion = 0;
|
|
4686
5005
|
try {
|
|
4687
5006
|
const currentConfig = await readAnyConfig(targetDir);
|
|
@@ -4692,7 +5011,7 @@ var init_sync = __esm({
|
|
|
4692
5011
|
}
|
|
4693
5012
|
let serverResponse;
|
|
4694
5013
|
try {
|
|
4695
|
-
serverResponse = await fetchConfigV2(apiKey);
|
|
5014
|
+
serverResponse = await fetchConfigV2(apiKey, { workspaceId });
|
|
4696
5015
|
} catch (err) {
|
|
4697
5016
|
if (err instanceof RelayError) {
|
|
4698
5017
|
printWarning(
|
|
@@ -4701,14 +5020,14 @@ var init_sync = __esm({
|
|
|
4701
5020
|
} else {
|
|
4702
5021
|
printWarning("Server unreachable, using cached config.");
|
|
4703
5022
|
}
|
|
4704
|
-
console.log(` ${
|
|
5023
|
+
console.log(` ${pc15.dim("Config may be stale. Retry when connected.")}`);
|
|
4705
5024
|
return;
|
|
4706
5025
|
}
|
|
4707
5026
|
if (!serverResponse.valid) {
|
|
4708
5027
|
printWarning("Server returned invalid config. Keeping current config.");
|
|
4709
5028
|
return;
|
|
4710
5029
|
}
|
|
4711
|
-
await mkdir11(
|
|
5030
|
+
await mkdir11(join24(targetDir, ".flydocs"), { recursive: true });
|
|
4712
5031
|
const configWithHash = applyConfigHash(serverResponse.config);
|
|
4713
5032
|
await writeConfig(targetDir, configWithHash);
|
|
4714
5033
|
changes.push("Updated .flydocs/config.json");
|
|
@@ -4717,10 +5036,11 @@ var init_sync = __esm({
|
|
|
4717
5036
|
try {
|
|
4718
5037
|
const templatesResponse = await fetchTemplates(
|
|
4719
5038
|
apiKey,
|
|
4720
|
-
currentTemplateVersion
|
|
5039
|
+
currentTemplateVersion,
|
|
5040
|
+
workspaceId
|
|
4721
5041
|
);
|
|
4722
5042
|
if (templatesResponse.templates.length > 0) {
|
|
4723
|
-
const templatesDir =
|
|
5043
|
+
const templatesDir = join24(
|
|
4724
5044
|
targetDir,
|
|
4725
5045
|
".claude",
|
|
4726
5046
|
"skills",
|
|
@@ -4731,10 +5051,10 @@ var init_sync = __esm({
|
|
|
4731
5051
|
for (const template of templatesResponse.templates) {
|
|
4732
5052
|
const filename = `${template.type}.md`;
|
|
4733
5053
|
const subdir = template.category === "issue" ? "issues" : template.category === "pr" ? "pr" : template.category === "comment" ? "." : ".";
|
|
4734
|
-
const templateDir =
|
|
5054
|
+
const templateDir = join24(templatesDir, subdir);
|
|
4735
5055
|
await mkdir11(templateDir, { recursive: true });
|
|
4736
|
-
await
|
|
4737
|
-
|
|
5056
|
+
await writeFile14(
|
|
5057
|
+
join24(templateDir, filename),
|
|
4738
5058
|
template.content,
|
|
4739
5059
|
"utf-8"
|
|
4740
5060
|
);
|
|
@@ -4764,221 +5084,6 @@ var init_sync = __esm({
|
|
|
4764
5084
|
}
|
|
4765
5085
|
});
|
|
4766
5086
|
|
|
4767
|
-
// src/commands/cleanup.ts
|
|
4768
|
-
var cleanup_exports = {};
|
|
4769
|
-
__export(cleanup_exports, {
|
|
4770
|
-
default: () => cleanup_default
|
|
4771
|
-
});
|
|
4772
|
-
import { defineCommand as defineCommand10 } from "citty";
|
|
4773
|
-
import pc15 from "picocolors";
|
|
4774
|
-
import { join as join24 } from "path";
|
|
4775
|
-
import { readFile as readFile15, writeFile as writeFile14, rm as rm6 } from "fs/promises";
|
|
4776
|
-
async function scanArtifacts(targetDir) {
|
|
4777
|
-
const actions = [];
|
|
4778
|
-
const localMePath = join24(targetDir, ".flydocs", "me.json");
|
|
4779
|
-
if (await pathExists(localMePath) && await pathExists(globalMePath())) {
|
|
4780
|
-
actions.push({
|
|
4781
|
-
description: "Remove .flydocs/me.json (migrated to ~/.flydocs/me.json)",
|
|
4782
|
-
path: localMePath,
|
|
4783
|
-
type: "file"
|
|
4784
|
-
});
|
|
4785
|
-
}
|
|
4786
|
-
const validationCachePath = join24(
|
|
4787
|
-
targetDir,
|
|
4788
|
-
".flydocs",
|
|
4789
|
-
"validation-cache.json"
|
|
4790
|
-
);
|
|
4791
|
-
if (await pathExists(validationCachePath)) {
|
|
4792
|
-
actions.push({
|
|
4793
|
-
description: "Remove .flydocs/validation-cache.json (replaced by configVersion)",
|
|
4794
|
-
path: validationCachePath,
|
|
4795
|
-
type: "file"
|
|
4796
|
-
});
|
|
4797
|
-
}
|
|
4798
|
-
const hasGlobalCreds = await pathExists(credentialsPath());
|
|
4799
|
-
for (const envFile of [".env", ".env.local"]) {
|
|
4800
|
-
const envPath = join24(targetDir, envFile);
|
|
4801
|
-
if (!await pathExists(envPath)) continue;
|
|
4802
|
-
const content = await readFile15(envPath, "utf-8");
|
|
4803
|
-
const lines = content.split("\n");
|
|
4804
|
-
for (const line of lines) {
|
|
4805
|
-
const trimmed = line.trim();
|
|
4806
|
-
if (hasGlobalCreds && trimmed.startsWith("FLYDOCS_API_KEY=")) {
|
|
4807
|
-
actions.push({
|
|
4808
|
-
description: `Remove FLYDOCS_API_KEY from ${envFile} (migrated to ~/.flydocs/credentials)`,
|
|
4809
|
-
path: envPath,
|
|
4810
|
-
type: "line"
|
|
4811
|
-
});
|
|
4812
|
-
}
|
|
4813
|
-
if (trimmed.startsWith("FLYDOCS_RELAY_URL=")) {
|
|
4814
|
-
actions.push({
|
|
4815
|
-
description: `Remove FLYDOCS_RELAY_URL from ${envFile}`,
|
|
4816
|
-
path: envPath,
|
|
4817
|
-
type: "line"
|
|
4818
|
-
});
|
|
4819
|
-
}
|
|
4820
|
-
}
|
|
4821
|
-
}
|
|
4822
|
-
try {
|
|
4823
|
-
const config = await readAnyConfig(targetDir);
|
|
4824
|
-
const rawContent = await readFile15(
|
|
4825
|
-
join24(targetDir, ".flydocs", "config.json"),
|
|
4826
|
-
"utf-8"
|
|
4827
|
-
);
|
|
4828
|
-
const raw = JSON.parse(rawContent);
|
|
4829
|
-
const ghostFields = ["provider", "statusMapping"];
|
|
4830
|
-
for (const field of ghostFields) {
|
|
4831
|
-
if (field in raw) {
|
|
4832
|
-
actions.push({
|
|
4833
|
-
description: `Remove ghost field "${field}" from config.json`,
|
|
4834
|
-
path: join24(targetDir, ".flydocs", "config.json"),
|
|
4835
|
-
type: "field"
|
|
4836
|
-
});
|
|
4837
|
-
}
|
|
4838
|
-
}
|
|
4839
|
-
if (isConfigV2(config)) {
|
|
4840
|
-
const v1OnlyFields = [
|
|
4841
|
-
"workspaceId",
|
|
4842
|
-
"issueLabels",
|
|
4843
|
-
"workspace",
|
|
4844
|
-
"onboardComplete",
|
|
4845
|
-
"sourceRepo",
|
|
4846
|
-
"designSystem",
|
|
4847
|
-
"aiLabor"
|
|
4848
|
-
];
|
|
4849
|
-
for (const field of v1OnlyFields) {
|
|
4850
|
-
if (field in raw) {
|
|
4851
|
-
actions.push({
|
|
4852
|
-
description: `Remove v1 field "${field}" from config.json (server-owned in v2)`,
|
|
4853
|
-
path: join24(targetDir, ".flydocs", "config.json"),
|
|
4854
|
-
type: "field"
|
|
4855
|
-
});
|
|
4856
|
-
}
|
|
4857
|
-
}
|
|
4858
|
-
}
|
|
4859
|
-
} catch {
|
|
4860
|
-
}
|
|
4861
|
-
return actions;
|
|
4862
|
-
}
|
|
4863
|
-
async function executeCleanup(targetDir, actions) {
|
|
4864
|
-
const fileRemovals = actions.filter((a) => a.type === "file");
|
|
4865
|
-
const lineRemovals = actions.filter((a) => a.type === "line");
|
|
4866
|
-
const fieldRemovals = actions.filter((a) => a.type === "field");
|
|
4867
|
-
for (const action of fileRemovals) {
|
|
4868
|
-
await rm6(action.path, { force: true });
|
|
4869
|
-
}
|
|
4870
|
-
const envFiles = /* @__PURE__ */ new Map();
|
|
4871
|
-
for (const action of lineRemovals) {
|
|
4872
|
-
if (!envFiles.has(action.path)) {
|
|
4873
|
-
const content = await readFile15(action.path, "utf-8");
|
|
4874
|
-
envFiles.set(action.path, content.split("\n"));
|
|
4875
|
-
}
|
|
4876
|
-
}
|
|
4877
|
-
for (const [envPath, lines] of envFiles) {
|
|
4878
|
-
const filtered = lines.filter((line) => {
|
|
4879
|
-
const trimmed = line.trim();
|
|
4880
|
-
return !trimmed.startsWith("FLYDOCS_API_KEY=") && !trimmed.startsWith("FLYDOCS_RELAY_URL=");
|
|
4881
|
-
});
|
|
4882
|
-
const hasContent = filtered.some(
|
|
4883
|
-
(l) => l.trim().length > 0 && !l.trim().startsWith("#")
|
|
4884
|
-
);
|
|
4885
|
-
if (!hasContent) {
|
|
4886
|
-
await rm6(envPath, { force: true });
|
|
4887
|
-
} else {
|
|
4888
|
-
await writeFile14(envPath, filtered.join("\n"), "utf-8");
|
|
4889
|
-
}
|
|
4890
|
-
}
|
|
4891
|
-
if (fieldRemovals.length > 0) {
|
|
4892
|
-
const configPath = join24(targetDir, ".flydocs", "config.json");
|
|
4893
|
-
const content = await readFile15(configPath, "utf-8");
|
|
4894
|
-
const config = JSON.parse(content);
|
|
4895
|
-
for (const action of fieldRemovals) {
|
|
4896
|
-
const match = action.description.match(/"(\w+)"/);
|
|
4897
|
-
if (match) {
|
|
4898
|
-
delete config[match[1]];
|
|
4899
|
-
}
|
|
4900
|
-
}
|
|
4901
|
-
await writeFile14(
|
|
4902
|
-
configPath,
|
|
4903
|
-
JSON.stringify(config, null, 2) + "\n",
|
|
4904
|
-
"utf-8"
|
|
4905
|
-
);
|
|
4906
|
-
}
|
|
4907
|
-
}
|
|
4908
|
-
var cleanup_default;
|
|
4909
|
-
var init_cleanup = __esm({
|
|
4910
|
-
"src/commands/cleanup.ts"() {
|
|
4911
|
-
"use strict";
|
|
4912
|
-
init_ui();
|
|
4913
|
-
init_fs_ops();
|
|
4914
|
-
init_config();
|
|
4915
|
-
init_types();
|
|
4916
|
-
init_global_config();
|
|
4917
|
-
cleanup_default = defineCommand10({
|
|
4918
|
-
meta: {
|
|
4919
|
-
name: "cleanup",
|
|
4920
|
-
description: "Remove legacy v1 artifacts after migration (dry-run by default)"
|
|
4921
|
-
},
|
|
4922
|
-
args: {
|
|
4923
|
-
confirm: {
|
|
4924
|
-
type: "boolean",
|
|
4925
|
-
description: "Actually remove artifacts (default: dry-run only)",
|
|
4926
|
-
default: false
|
|
4927
|
-
},
|
|
4928
|
-
path: {
|
|
4929
|
-
type: "string",
|
|
4930
|
-
description: "Path to project directory"
|
|
4931
|
-
}
|
|
4932
|
-
},
|
|
4933
|
-
async run({ args }) {
|
|
4934
|
-
const targetDir = args.path ?? process.cwd();
|
|
4935
|
-
console.log();
|
|
4936
|
-
console.log(` ${pc15.bold("FlyDocs Cleanup")}`);
|
|
4937
|
-
console.log();
|
|
4938
|
-
const hasConfig = await pathExists(
|
|
4939
|
-
join24(targetDir, ".flydocs", "config.json")
|
|
4940
|
-
);
|
|
4941
|
-
if (!hasConfig) {
|
|
4942
|
-
printError("No .flydocs/config.json found. Run flydocs init first.");
|
|
4943
|
-
process.exit(1);
|
|
4944
|
-
}
|
|
4945
|
-
const hasGlobalCreds = await pathExists(credentialsPath());
|
|
4946
|
-
if (!hasGlobalCreds) {
|
|
4947
|
-
printWarning(
|
|
4948
|
-
"No global credentials found. Run flydocs init to set up credentials before cleanup."
|
|
4949
|
-
);
|
|
4950
|
-
}
|
|
4951
|
-
const actions = await scanArtifacts(targetDir);
|
|
4952
|
-
if (actions.length === 0) {
|
|
4953
|
-
printStatus("No legacy artifacts found. Already clean.");
|
|
4954
|
-
console.log();
|
|
4955
|
-
return;
|
|
4956
|
-
}
|
|
4957
|
-
const mode = args.confirm ? "Removing" : "Would remove";
|
|
4958
|
-
printInfo(`${mode} ${actions.length} legacy artifact(s):`);
|
|
4959
|
-
console.log();
|
|
4960
|
-
for (const action of actions) {
|
|
4961
|
-
const icon = args.confirm ? pc15.red("-") : pc15.yellow("?");
|
|
4962
|
-
console.log(` ${icon} ${action.description}`);
|
|
4963
|
-
}
|
|
4964
|
-
console.log();
|
|
4965
|
-
if (!args.confirm) {
|
|
4966
|
-
printInfo(
|
|
4967
|
-
`Dry-run complete. Run ${pc15.cyan("flydocs cleanup --confirm")} to remove.`
|
|
4968
|
-
);
|
|
4969
|
-
console.log();
|
|
4970
|
-
return;
|
|
4971
|
-
}
|
|
4972
|
-
await executeCleanup(targetDir, actions);
|
|
4973
|
-
printCompletionBox("Cleanup Complete", [
|
|
4974
|
-
`${pc15.green("+")} Removed ${actions.length} legacy artifact(s)`
|
|
4975
|
-
]);
|
|
4976
|
-
console.log();
|
|
4977
|
-
}
|
|
4978
|
-
});
|
|
4979
|
-
}
|
|
4980
|
-
});
|
|
4981
|
-
|
|
4982
5087
|
// src/commands/upgrade.ts
|
|
4983
5088
|
var upgrade_exports = {};
|
|
4984
5089
|
__export(upgrade_exports, {
|