md4ai 0.12.0 → 0.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.bundled.js +243 -93
- package/package.json +1 -1
package/dist/index.bundled.js
CHANGED
|
@@ -73,7 +73,7 @@ var CURRENT_VERSION;
|
|
|
73
73
|
var init_check_update = __esm({
|
|
74
74
|
"dist/check-update.js"() {
|
|
75
75
|
"use strict";
|
|
76
|
-
CURRENT_VERSION = true ? "0.
|
|
76
|
+
CURRENT_VERSION = true ? "0.13.1" : "0.0.0-dev";
|
|
77
77
|
}
|
|
78
78
|
});
|
|
79
79
|
|
|
@@ -1656,21 +1656,40 @@ var init_marketplace_scanner = __esm({
|
|
|
1656
1656
|
|
|
1657
1657
|
// dist/doppler/auth.js
|
|
1658
1658
|
async function resolveDopplerToken() {
|
|
1659
|
+
const { join: join17 } = await import("node:path");
|
|
1660
|
+
const { homedir: homedir10 } = await import("node:os");
|
|
1661
|
+
const credPath = join17(homedir10(), ".md4ai", "credentials.json");
|
|
1659
1662
|
const creds = await loadCredentials();
|
|
1660
1663
|
if (creds?.dopplerToken) {
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1664
|
+
return { token: creds.dopplerToken, sourcePath: credPath };
|
|
1665
|
+
}
|
|
1666
|
+
if (!creds?.accessToken || !creds?.userId)
|
|
1667
|
+
return null;
|
|
1668
|
+
try {
|
|
1669
|
+
let supabase = createSupabaseClient(getAnonKey(), creds.accessToken);
|
|
1670
|
+
let userId = creds.userId;
|
|
1671
|
+
if (Date.now() > creds.expiresAt) {
|
|
1672
|
+
const refreshed = await refreshSession();
|
|
1673
|
+
if (!refreshed)
|
|
1674
|
+
return null;
|
|
1675
|
+
supabase = refreshed.supabase;
|
|
1676
|
+
userId = refreshed.userId;
|
|
1677
|
+
}
|
|
1678
|
+
const { data } = await supabase.from("user_secrets").select("doppler_token").eq("user_id", userId).maybeSingle();
|
|
1679
|
+
if (!data?.doppler_token)
|
|
1680
|
+
return null;
|
|
1681
|
+
await mergeCredentials({ dopplerToken: data.doppler_token });
|
|
1682
|
+
return { token: data.doppler_token, sourcePath: "Supabase (cached locally)" };
|
|
1683
|
+
} catch {
|
|
1684
|
+
return null;
|
|
1667
1685
|
}
|
|
1668
|
-
return null;
|
|
1669
1686
|
}
|
|
1670
1687
|
var init_auth3 = __esm({
|
|
1671
1688
|
"dist/doppler/auth.js"() {
|
|
1672
1689
|
"use strict";
|
|
1673
1690
|
init_config();
|
|
1691
|
+
init_auth();
|
|
1692
|
+
init_dist();
|
|
1674
1693
|
}
|
|
1675
1694
|
});
|
|
1676
1695
|
|
|
@@ -2175,7 +2194,7 @@ var init_push_toolings = __esm({
|
|
|
2175
2194
|
|
|
2176
2195
|
// dist/commands/push-health-results.js
|
|
2177
2196
|
import chalk11 from "chalk";
|
|
2178
|
-
async function pushHealthResults(supabase, folderId, manifest) {
|
|
2197
|
+
async function pushHealthResults(supabase, folderId, manifest, deviceId) {
|
|
2179
2198
|
const { data: checks } = await supabase.from("env_health_checks").select("id, check_type, check_config").eq("folder_id", folderId).eq("enabled", true);
|
|
2180
2199
|
if (!checks?.length)
|
|
2181
2200
|
return;
|
|
@@ -2193,7 +2212,8 @@ async function pushHealthResults(supabase, folderId, manifest) {
|
|
|
2193
2212
|
check_id: chk.id,
|
|
2194
2213
|
status: localStatus === "present" ? "pass" : "fail",
|
|
2195
2214
|
message: localStatus === "present" ? "Set" : "Missing",
|
|
2196
|
-
ran_at: ranAt
|
|
2215
|
+
ran_at: ranAt,
|
|
2216
|
+
device_id: deviceId ?? null
|
|
2197
2217
|
});
|
|
2198
2218
|
}
|
|
2199
2219
|
} else if (chk.check_type === "file_exists") {
|
|
@@ -2201,7 +2221,8 @@ async function pushHealthResults(supabase, folderId, manifest) {
|
|
|
2201
2221
|
check_id: chk.id,
|
|
2202
2222
|
status: "pass",
|
|
2203
2223
|
message: "Found",
|
|
2204
|
-
ran_at: ranAt
|
|
2224
|
+
ran_at: ranAt,
|
|
2225
|
+
device_id: deviceId ?? null
|
|
2205
2226
|
});
|
|
2206
2227
|
} else if (chk.check_type === "gh_secret") {
|
|
2207
2228
|
const variable = config2.secret;
|
|
@@ -2211,7 +2232,8 @@ async function pushHealthResults(supabase, folderId, manifest) {
|
|
|
2211
2232
|
check_id: chk.id,
|
|
2212
2233
|
status: ghStatus === "present" ? "pass" : ghStatus === "missing" ? "fail" : "warn",
|
|
2213
2234
|
message: ghStatus === "present" ? "Exists" : ghStatus === "missing" ? "Missing" : "Unknown",
|
|
2214
|
-
ran_at: ranAt
|
|
2235
|
+
ran_at: ranAt,
|
|
2236
|
+
device_id: deviceId ?? null
|
|
2215
2237
|
});
|
|
2216
2238
|
} else if (chk.check_type === "vercel_env") {
|
|
2217
2239
|
const variable = config2.variable;
|
|
@@ -2226,14 +2248,16 @@ async function pushHealthResults(supabase, folderId, manifest) {
|
|
|
2226
2248
|
check_id: chk.id,
|
|
2227
2249
|
status: hasTarget ? "pass" : "warn",
|
|
2228
2250
|
message: hasTarget ? `Present (${target})` : `Present but not in ${target}`,
|
|
2229
|
-
ran_at: ranAt
|
|
2251
|
+
ran_at: ranAt,
|
|
2252
|
+
device_id: deviceId ?? null
|
|
2230
2253
|
});
|
|
2231
2254
|
} else {
|
|
2232
2255
|
results.push({
|
|
2233
2256
|
check_id: chk.id,
|
|
2234
2257
|
status: "fail",
|
|
2235
2258
|
message: `Not found in ${projectName}`,
|
|
2236
|
-
ran_at: ranAt
|
|
2259
|
+
ran_at: ranAt,
|
|
2260
|
+
device_id: deviceId ?? null
|
|
2237
2261
|
});
|
|
2238
2262
|
}
|
|
2239
2263
|
}
|
|
@@ -2369,10 +2393,12 @@ async function mapCommand(path, options) {
|
|
|
2369
2393
|
Local preview: ${htmlPath}`));
|
|
2370
2394
|
if (!options.offline) {
|
|
2371
2395
|
try {
|
|
2372
|
-
const { supabase } = await getAuthenticatedClient();
|
|
2396
|
+
const { supabase, userId } = await getAuthenticatedClient();
|
|
2373
2397
|
const { data: devicePaths } = await supabase.from("device_paths").select("folder_id, device_name").eq("path", projectRoot);
|
|
2374
2398
|
if (devicePaths?.length) {
|
|
2375
2399
|
const { folder_id, device_name } = devicePaths[0];
|
|
2400
|
+
const { data: deviceRow } = await supabase.from("devices").select("id").eq("user_id", userId).eq("device_name", device_name).single();
|
|
2401
|
+
const deviceId = deviceRow?.id;
|
|
2376
2402
|
const { data: proposedFiles } = await supabase.from("folder_files").select("id, file_path, proposed_at").eq("folder_id", folder_id).eq("proposed_for_deletion", true);
|
|
2377
2403
|
if (proposedFiles?.length && process.stdin.isTTY) {
|
|
2378
2404
|
const { checkbox } = await import("@inquirer/prompts");
|
|
@@ -2436,39 +2462,61 @@ ${proposedFiles.length} file(s) proposed for deletion:
|
|
|
2436
2462
|
if (result.doppler) {
|
|
2437
2463
|
updatePayload.doppler_json = result.doppler;
|
|
2438
2464
|
}
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
await pushToolings(supabase, folder_id, result.toolings);
|
|
2444
|
-
const manifestForHealth = result.envManifest ?? storedManifest;
|
|
2445
|
-
if (manifestForHealth) {
|
|
2446
|
-
await pushHealthResults(supabase, folder_id, manifestForHealth);
|
|
2465
|
+
try {
|
|
2466
|
+
const { error } = await supabase.from("claude_folders").update(updatePayload).eq("id", folder_id);
|
|
2467
|
+
if (error) {
|
|
2468
|
+
console.log(chalk12.dim(`Debug: claude_folders update skipped (${error.message})`));
|
|
2447
2469
|
}
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2470
|
+
} catch (err) {
|
|
2471
|
+
console.log(chalk12.dim(`Debug: claude_folders update skipped (${err instanceof Error ? err.message : String(err)})`));
|
|
2472
|
+
}
|
|
2473
|
+
if (deviceId) {
|
|
2474
|
+
await supabase.from("device_scans").upsert({
|
|
2475
|
+
folder_id,
|
|
2476
|
+
device_id: deviceId,
|
|
2477
|
+
user_id: userId,
|
|
2478
|
+
graph_json: result.graph,
|
|
2479
|
+
orphans_json: result.orphans,
|
|
2480
|
+
skills_table_json: result.skills,
|
|
2481
|
+
stale_files_json: result.staleFiles,
|
|
2482
|
+
broken_refs_json: result.brokenRefs,
|
|
2483
|
+
env_manifest_json: result.envManifest,
|
|
2484
|
+
doppler_json: result.doppler,
|
|
2485
|
+
marketplace_plugins_json: result.marketplacePlugins,
|
|
2486
|
+
data_hash: result.dataHash,
|
|
2487
|
+
scanned_at: result.scannedAt,
|
|
2488
|
+
cli_version: CURRENT_VERSION
|
|
2489
|
+
}, { onConflict: "folder_id,device_id" });
|
|
2490
|
+
}
|
|
2491
|
+
await pushToolings(supabase, folder_id, result.toolings);
|
|
2492
|
+
const manifestForHealth = result.envManifest ?? storedManifest;
|
|
2493
|
+
if (manifestForHealth) {
|
|
2494
|
+
await pushHealthResults(supabase, folder_id, manifestForHealth, deviceId);
|
|
2495
|
+
}
|
|
2496
|
+
await supabase.from("device_paths").update({ last_synced: (/* @__PURE__ */ new Date()).toISOString() }).eq("folder_id", folder_id).eq("device_name", device_name);
|
|
2497
|
+
await saveState({
|
|
2498
|
+
lastFolderId: folder_id,
|
|
2499
|
+
lastDeviceName: device_name,
|
|
2500
|
+
lastSyncAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2501
|
+
});
|
|
2502
|
+
console.log(chalk12.green("Synced to Supabase."));
|
|
2503
|
+
console.log(chalk12.cyan(`
|
|
2456
2504
|
https://www.md4ai.com/project/${folder_id}
|
|
2457
2505
|
`));
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
}
|
|
2470
|
-
console.log(chalk12.green(` Uploaded ${configFiles.length} config file(s).`));
|
|
2506
|
+
const graphPaths = result.graph.nodes.map((n) => n.filePath);
|
|
2507
|
+
const configFiles = await readClaudeConfigFiles(projectRoot, graphPaths);
|
|
2508
|
+
if (configFiles.length > 0) {
|
|
2509
|
+
for (const file of configFiles) {
|
|
2510
|
+
await supabase.from("folder_files").upsert({
|
|
2511
|
+
folder_id,
|
|
2512
|
+
file_path: file.filePath,
|
|
2513
|
+
content: file.content,
|
|
2514
|
+
size_bytes: file.sizeBytes,
|
|
2515
|
+
last_modified: file.lastModified,
|
|
2516
|
+
device_id: deviceId
|
|
2517
|
+
}, { onConflict: "folder_id,file_path,device_id" });
|
|
2471
2518
|
}
|
|
2519
|
+
console.log(chalk12.green(` Uploaded ${configFiles.length} config file(s).`));
|
|
2472
2520
|
}
|
|
2473
2521
|
} else {
|
|
2474
2522
|
console.log(chalk12.yellow("\nThis folder is not linked to a project on your dashboard."));
|
|
@@ -2480,7 +2528,7 @@ ${proposedFiles.length} file(s) proposed for deletion:
|
|
|
2480
2528
|
if (!shouldLink) {
|
|
2481
2529
|
console.log(chalk12.dim("Skipped \u2014 local preview still generated."));
|
|
2482
2530
|
} else {
|
|
2483
|
-
const { supabase: sb, userId } = await getAuthenticatedClient();
|
|
2531
|
+
const { supabase: sb, userId: userId2 } = await getAuthenticatedClient();
|
|
2484
2532
|
const { data: folders } = await sb.from("claude_folders").select("id, name").order("name");
|
|
2485
2533
|
const choices = [
|
|
2486
2534
|
{ name: "+ Create a new project", value: "__new__" },
|
|
@@ -2496,7 +2544,7 @@ ${proposedFiles.length} file(s) proposed for deletion:
|
|
|
2496
2544
|
message: "Project name:",
|
|
2497
2545
|
default: basename2(projectRoot)
|
|
2498
2546
|
});
|
|
2499
|
-
const { data: newFolder, error: createErr } = await sb.from("claude_folders").insert({ user_id:
|
|
2547
|
+
const { data: newFolder, error: createErr } = await sb.from("claude_folders").insert({ user_id: userId2, name: projectName }).select("id").single();
|
|
2500
2548
|
if (createErr || !newFolder) {
|
|
2501
2549
|
console.error(chalk12.red(`Failed to create project: ${createErr?.message}`));
|
|
2502
2550
|
return;
|
|
@@ -2509,33 +2557,60 @@ ${proposedFiles.length} file(s) proposed for deletion:
|
|
|
2509
2557
|
const deviceName = detectDeviceName();
|
|
2510
2558
|
const osType = detectOs2();
|
|
2511
2559
|
await sb.from("devices").upsert({
|
|
2512
|
-
user_id:
|
|
2560
|
+
user_id: userId2,
|
|
2513
2561
|
device_name: deviceName,
|
|
2514
2562
|
os_type: osType
|
|
2515
2563
|
}, { onConflict: "user_id,device_name" });
|
|
2564
|
+
const { data: inlineDeviceRow } = await sb.from("devices").select("id").eq("user_id", userId2).eq("device_name", deviceName).single();
|
|
2565
|
+
const inlineDeviceId = inlineDeviceRow?.id;
|
|
2516
2566
|
await sb.from("device_paths").upsert({
|
|
2517
|
-
user_id:
|
|
2567
|
+
user_id: userId2,
|
|
2518
2568
|
folder_id: folderId,
|
|
2519
2569
|
device_name: deviceName,
|
|
2520
2570
|
os_type: osType,
|
|
2521
2571
|
path: projectRoot,
|
|
2522
2572
|
last_synced: (/* @__PURE__ */ new Date()).toISOString()
|
|
2523
2573
|
}, { onConflict: "folder_id,device_name" });
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2574
|
+
try {
|
|
2575
|
+
const { error: inlineFolderErr } = await sb.from("claude_folders").update({
|
|
2576
|
+
graph_json: result.graph,
|
|
2577
|
+
orphans_json: result.orphans,
|
|
2578
|
+
broken_refs_json: result.brokenRefs,
|
|
2579
|
+
skills_table_json: result.skills,
|
|
2580
|
+
stale_files_json: result.staleFiles,
|
|
2581
|
+
env_manifest_json: result.envManifest,
|
|
2582
|
+
doppler_json: result.doppler,
|
|
2583
|
+
marketplace_plugins_json: result.marketplacePlugins,
|
|
2584
|
+
last_scanned: result.scannedAt,
|
|
2585
|
+
data_hash: result.dataHash
|
|
2586
|
+
}).eq("id", folderId);
|
|
2587
|
+
if (inlineFolderErr) {
|
|
2588
|
+
console.log(chalk12.dim(`Debug: claude_folders update skipped (${inlineFolderErr.message})`));
|
|
2589
|
+
}
|
|
2590
|
+
} catch (err) {
|
|
2591
|
+
console.log(chalk12.dim(`Debug: claude_folders update skipped (${err instanceof Error ? err.message : String(err)})`));
|
|
2592
|
+
}
|
|
2593
|
+
if (inlineDeviceId) {
|
|
2594
|
+
await sb.from("device_scans").upsert({
|
|
2595
|
+
folder_id: folderId,
|
|
2596
|
+
device_id: inlineDeviceId,
|
|
2597
|
+
user_id: userId2,
|
|
2598
|
+
graph_json: result.graph,
|
|
2599
|
+
orphans_json: result.orphans,
|
|
2600
|
+
skills_table_json: result.skills,
|
|
2601
|
+
stale_files_json: result.staleFiles,
|
|
2602
|
+
broken_refs_json: result.brokenRefs,
|
|
2603
|
+
env_manifest_json: result.envManifest,
|
|
2604
|
+
doppler_json: result.doppler,
|
|
2605
|
+
marketplace_plugins_json: result.marketplacePlugins,
|
|
2606
|
+
data_hash: result.dataHash,
|
|
2607
|
+
scanned_at: result.scannedAt,
|
|
2608
|
+
cli_version: CURRENT_VERSION
|
|
2609
|
+
}, { onConflict: "folder_id,device_id" });
|
|
2610
|
+
}
|
|
2536
2611
|
await pushToolings(sb, folderId, result.toolings);
|
|
2537
2612
|
if (result.envManifest) {
|
|
2538
|
-
await pushHealthResults(sb, folderId, result.envManifest);
|
|
2613
|
+
await pushHealthResults(sb, folderId, result.envManifest, inlineDeviceId);
|
|
2539
2614
|
}
|
|
2540
2615
|
const graphPaths2 = result.graph.nodes.map((n) => n.filePath);
|
|
2541
2616
|
const configFiles = await readClaudeConfigFiles(projectRoot, graphPaths2);
|
|
@@ -2545,8 +2620,9 @@ ${proposedFiles.length} file(s) proposed for deletion:
|
|
|
2545
2620
|
file_path: file.filePath,
|
|
2546
2621
|
content: file.content,
|
|
2547
2622
|
size_bytes: file.sizeBytes,
|
|
2548
|
-
last_modified: file.lastModified
|
|
2549
|
-
|
|
2623
|
+
last_modified: file.lastModified,
|
|
2624
|
+
device_id: inlineDeviceId
|
|
2625
|
+
}, { onConflict: "folder_id,file_path,device_id" });
|
|
2550
2626
|
}
|
|
2551
2627
|
await saveState({
|
|
2552
2628
|
lastFolderId: folderId,
|
|
@@ -2591,7 +2667,7 @@ function isValidProjectPath(p) {
|
|
|
2591
2667
|
return resolved.startsWith("/") && !resolved.includes("..") && existsSync11(resolved);
|
|
2592
2668
|
}
|
|
2593
2669
|
async function syncCommand(options) {
|
|
2594
|
-
const { supabase } = await getAuthenticatedClient();
|
|
2670
|
+
const { supabase, userId } = await getAuthenticatedClient();
|
|
2595
2671
|
if (options.all) {
|
|
2596
2672
|
const { data: devices, error } = await supabase.from("device_paths").select("folder_id, device_name, path");
|
|
2597
2673
|
if (error || !devices?.length) {
|
|
@@ -2610,16 +2686,41 @@ async function syncCommand(options) {
|
|
|
2610
2686
|
}
|
|
2611
2687
|
try {
|
|
2612
2688
|
const result = await scanProject(device.path);
|
|
2613
|
-
await supabase.from("
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2689
|
+
const { data: allDeviceRow } = await supabase.from("devices").select("id").eq("user_id", userId).eq("device_name", device.device_name).single();
|
|
2690
|
+
const allDeviceId = allDeviceRow?.id;
|
|
2691
|
+
try {
|
|
2692
|
+
const { error: allFolderErr } = await supabase.from("claude_folders").update({
|
|
2693
|
+
graph_json: result.graph,
|
|
2694
|
+
orphans_json: result.orphans,
|
|
2695
|
+
broken_refs_json: result.brokenRefs,
|
|
2696
|
+
skills_table_json: result.skills,
|
|
2697
|
+
stale_files_json: result.staleFiles,
|
|
2698
|
+
env_manifest_json: result.envManifest,
|
|
2699
|
+
last_scanned: result.scannedAt,
|
|
2700
|
+
data_hash: result.dataHash
|
|
2701
|
+
}).eq("id", device.folder_id);
|
|
2702
|
+
if (allFolderErr) {
|
|
2703
|
+
console.log(chalk15.dim(` Debug: claude_folders update skipped (${allFolderErr.message})`));
|
|
2704
|
+
}
|
|
2705
|
+
} catch (folderErr) {
|
|
2706
|
+
console.log(chalk15.dim(` Debug: claude_folders update skipped (${folderErr instanceof Error ? folderErr.message : String(folderErr)})`));
|
|
2707
|
+
}
|
|
2708
|
+
if (allDeviceId) {
|
|
2709
|
+
await supabase.from("device_scans").upsert({
|
|
2710
|
+
folder_id: device.folder_id,
|
|
2711
|
+
device_id: allDeviceId,
|
|
2712
|
+
user_id: userId,
|
|
2713
|
+
graph_json: result.graph,
|
|
2714
|
+
orphans_json: result.orphans,
|
|
2715
|
+
skills_table_json: result.skills,
|
|
2716
|
+
stale_files_json: result.staleFiles,
|
|
2717
|
+
broken_refs_json: result.brokenRefs,
|
|
2718
|
+
env_manifest_json: result.envManifest,
|
|
2719
|
+
data_hash: result.dataHash,
|
|
2720
|
+
scanned_at: result.scannedAt,
|
|
2721
|
+
cli_version: CURRENT_VERSION
|
|
2722
|
+
}, { onConflict: "folder_id,device_id" });
|
|
2723
|
+
}
|
|
2623
2724
|
await pushToolings(supabase, device.folder_id, result.toolings);
|
|
2624
2725
|
await supabase.from("device_paths").update({ last_synced: (/* @__PURE__ */ new Date()).toISOString() }).eq("folder_id", device.folder_id).eq("device_name", device.device_name);
|
|
2625
2726
|
console.log(chalk15.green(` Done: ${device.device_name}`));
|
|
@@ -2650,15 +2751,39 @@ async function syncCommand(options) {
|
|
|
2650
2751
|
console.log(chalk15.yellow(` ${proposedSingle.length} file(s) proposed for deletion \u2014 run \`md4ai scan\` to review.`));
|
|
2651
2752
|
}
|
|
2652
2753
|
const result = await scanProject(device.path);
|
|
2653
|
-
await supabase.from("
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2754
|
+
const { data: singleDeviceRow } = await supabase.from("devices").select("id").eq("user_id", userId).eq("device_name", device.device_name).single();
|
|
2755
|
+
const singleDeviceId = singleDeviceRow?.id;
|
|
2756
|
+
try {
|
|
2757
|
+
const { error: singleFolderErr } = await supabase.from("claude_folders").update({
|
|
2758
|
+
graph_json: result.graph,
|
|
2759
|
+
orphans_json: result.orphans,
|
|
2760
|
+
broken_refs_json: result.brokenRefs,
|
|
2761
|
+
skills_table_json: result.skills,
|
|
2762
|
+
stale_files_json: result.staleFiles,
|
|
2763
|
+
last_scanned: result.scannedAt,
|
|
2764
|
+
data_hash: result.dataHash
|
|
2765
|
+
}).eq("id", device.folder_id);
|
|
2766
|
+
if (singleFolderErr) {
|
|
2767
|
+
console.log(chalk15.dim(`Debug: claude_folders update skipped (${singleFolderErr.message})`));
|
|
2768
|
+
}
|
|
2769
|
+
} catch (err) {
|
|
2770
|
+
console.log(chalk15.dim(`Debug: claude_folders update skipped (${err instanceof Error ? err.message : String(err)})`));
|
|
2771
|
+
}
|
|
2772
|
+
if (singleDeviceId) {
|
|
2773
|
+
await supabase.from("device_scans").upsert({
|
|
2774
|
+
folder_id: device.folder_id,
|
|
2775
|
+
device_id: singleDeviceId,
|
|
2776
|
+
user_id: userId,
|
|
2777
|
+
graph_json: result.graph,
|
|
2778
|
+
orphans_json: result.orphans,
|
|
2779
|
+
skills_table_json: result.skills,
|
|
2780
|
+
stale_files_json: result.staleFiles,
|
|
2781
|
+
broken_refs_json: result.brokenRefs,
|
|
2782
|
+
data_hash: result.dataHash,
|
|
2783
|
+
scanned_at: result.scannedAt,
|
|
2784
|
+
cli_version: CURRENT_VERSION
|
|
2785
|
+
}, { onConflict: "folder_id,device_id" });
|
|
2786
|
+
}
|
|
2662
2787
|
await pushToolings(supabase, device.folder_id, result.toolings);
|
|
2663
2788
|
await supabase.from("device_paths").update({ last_synced: (/* @__PURE__ */ new Date()).toISOString() }).eq("folder_id", device.folder_id).eq("device_name", device.device_name);
|
|
2664
2789
|
await saveState({ lastSyncAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
@@ -2672,6 +2797,7 @@ var init_sync = __esm({
|
|
|
2672
2797
|
init_config();
|
|
2673
2798
|
init_scanner();
|
|
2674
2799
|
init_push_toolings();
|
|
2800
|
+
init_check_update();
|
|
2675
2801
|
}
|
|
2676
2802
|
});
|
|
2677
2803
|
|
|
@@ -3780,6 +3906,7 @@ init_config();
|
|
|
3780
3906
|
init_scanner();
|
|
3781
3907
|
init_push_toolings();
|
|
3782
3908
|
init_device_utils();
|
|
3909
|
+
init_check_update();
|
|
3783
3910
|
import { resolve as resolve6 } from "node:path";
|
|
3784
3911
|
import chalk16 from "chalk";
|
|
3785
3912
|
async function linkCommand(projectId) {
|
|
@@ -3805,6 +3932,8 @@ Linking "${folder.name}" to this device...
|
|
|
3805
3932
|
device_name: deviceName,
|
|
3806
3933
|
os_type: osType
|
|
3807
3934
|
}, { onConflict: "user_id,device_name" });
|
|
3935
|
+
const { data: deviceRow } = await supabase.from("devices").select("id").eq("user_id", userId).eq("device_name", deviceName).single();
|
|
3936
|
+
const deviceId = deviceRow.id;
|
|
3808
3937
|
const { data: existing } = await supabase.from("device_paths").select("id").eq("folder_id", folder.id).eq("device_name", deviceName).maybeSingle();
|
|
3809
3938
|
if (existing) {
|
|
3810
3939
|
await supabase.from("device_paths").update({ path: cwd, os_type: osType, last_synced: (/* @__PURE__ */ new Date()).toISOString() }).eq("id", existing.id);
|
|
@@ -3832,21 +3961,41 @@ Linking "${folder.name}" to this device...
|
|
|
3832
3961
|
console.log(` Env Vars: ${result.envManifest?.variables.length ?? 0} (${result.envManifest ? "manifest found" : "no manifest"})`);
|
|
3833
3962
|
console.log(` Doppler: ${result.doppler ? `${result.doppler.configs.length} config(s) \u2014 ${result.doppler.project}` : "see above"}`);
|
|
3834
3963
|
console.log(` Plugins: ${result.marketplacePlugins.length} (${result.marketplacePlugins.reduce((n, p) => n + p.skills.length, 0)} skills)`);
|
|
3835
|
-
|
|
3964
|
+
try {
|
|
3965
|
+
const { error: scanErr } = await supabase.from("claude_folders").update({
|
|
3966
|
+
graph_json: result.graph,
|
|
3967
|
+
orphans_json: result.orphans,
|
|
3968
|
+
broken_refs_json: result.brokenRefs,
|
|
3969
|
+
skills_table_json: result.skills,
|
|
3970
|
+
stale_files_json: result.staleFiles,
|
|
3971
|
+
env_manifest_json: result.envManifest,
|
|
3972
|
+
doppler_json: result.doppler,
|
|
3973
|
+
marketplace_plugins_json: result.marketplacePlugins,
|
|
3974
|
+
last_scanned: result.scannedAt,
|
|
3975
|
+
data_hash: result.dataHash
|
|
3976
|
+
}).eq("id", folder.id);
|
|
3977
|
+
if (scanErr) {
|
|
3978
|
+
console.log(chalk16.dim(`Debug: claude_folders update skipped (${scanErr.message})`));
|
|
3979
|
+
}
|
|
3980
|
+
} catch (err) {
|
|
3981
|
+
console.log(chalk16.dim(`Debug: claude_folders update skipped (${err instanceof Error ? err.message : String(err)})`));
|
|
3982
|
+
}
|
|
3983
|
+
await supabase.from("device_scans").upsert({
|
|
3984
|
+
folder_id: folder.id,
|
|
3985
|
+
device_id: deviceId,
|
|
3986
|
+
user_id: userId,
|
|
3836
3987
|
graph_json: result.graph,
|
|
3837
3988
|
orphans_json: result.orphans,
|
|
3838
|
-
broken_refs_json: result.brokenRefs,
|
|
3839
3989
|
skills_table_json: result.skills,
|
|
3840
3990
|
stale_files_json: result.staleFiles,
|
|
3991
|
+
broken_refs_json: result.brokenRefs,
|
|
3841
3992
|
env_manifest_json: result.envManifest,
|
|
3842
3993
|
doppler_json: result.doppler,
|
|
3843
3994
|
marketplace_plugins_json: result.marketplacePlugins,
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
console.error(chalk16.yellow(`Scan upload warning: ${scanErr.message}`));
|
|
3849
|
-
}
|
|
3995
|
+
data_hash: result.dataHash,
|
|
3996
|
+
scanned_at: result.scannedAt,
|
|
3997
|
+
cli_version: CURRENT_VERSION
|
|
3998
|
+
}, { onConflict: "folder_id,device_id" });
|
|
3850
3999
|
await pushToolings(supabase, folder.id, result.toolings);
|
|
3851
4000
|
const graphPaths = result.graph.nodes.map((n) => n.filePath);
|
|
3852
4001
|
const configFiles = await readClaudeConfigFiles(cwd, graphPaths);
|
|
@@ -3857,8 +4006,9 @@ Linking "${folder.name}" to this device...
|
|
|
3857
4006
|
file_path: file.filePath,
|
|
3858
4007
|
content: file.content,
|
|
3859
4008
|
size_bytes: file.sizeBytes,
|
|
3860
|
-
last_modified: file.lastModified
|
|
3861
|
-
|
|
4009
|
+
last_modified: file.lastModified,
|
|
4010
|
+
device_id: deviceId
|
|
4011
|
+
}, { onConflict: "folder_id,file_path,device_id" });
|
|
3862
4012
|
}
|
|
3863
4013
|
console.log(chalk16.green(` Uploaded ${configFiles.length} config file(s).`));
|
|
3864
4014
|
}
|