@keepgoingdev/cli 1.2.0 → 1.2.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.js +92 -6
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1096,7 +1096,14 @@ function getLicenseForFeature(feature) {
|
|
|
1096
1096
|
return features?.includes(feature);
|
|
1097
1097
|
});
|
|
1098
1098
|
}
|
|
1099
|
+
function getAllLicensesNeedingRevalidation() {
|
|
1100
|
+
return getActiveLicenses().filter((l) => needsRevalidation(l));
|
|
1101
|
+
}
|
|
1099
1102
|
var REVALIDATION_THRESHOLD_MS = 24 * 60 * 60 * 1e3;
|
|
1103
|
+
function needsRevalidation(entry) {
|
|
1104
|
+
const lastValidated = new Date(entry.lastValidatedAt).getTime();
|
|
1105
|
+
return Date.now() - lastValidated > REVALIDATION_THRESHOLD_MS;
|
|
1106
|
+
}
|
|
1100
1107
|
|
|
1101
1108
|
// ../../packages/shared/src/featureGate.ts
|
|
1102
1109
|
var DefaultFeatureGate = class {
|
|
@@ -1690,6 +1697,39 @@ async function activateLicense(licenseKey, instanceName, options) {
|
|
|
1690
1697
|
return { valid: false, error: message };
|
|
1691
1698
|
}
|
|
1692
1699
|
}
|
|
1700
|
+
async function validateLicense(licenseKey, instanceId, options) {
|
|
1701
|
+
try {
|
|
1702
|
+
const res = await fetchWithTimeout(`${BASE_URL}/validate`, {
|
|
1703
|
+
method: "POST",
|
|
1704
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
1705
|
+
body: new URLSearchParams({ license_key: licenseKey, instance_id: instanceId })
|
|
1706
|
+
});
|
|
1707
|
+
const data = await safeJson(res);
|
|
1708
|
+
if (!res.ok || !data?.valid) {
|
|
1709
|
+
return { valid: false, isNetworkError: false, error: data?.error || `Validation failed (${res.status})` };
|
|
1710
|
+
}
|
|
1711
|
+
if (!options?.allowTestMode && data.license_key?.test_mode) {
|
|
1712
|
+
return { valid: false, isNetworkError: false, error: "This is a test license key. Please use a production license key from your purchase confirmation." };
|
|
1713
|
+
}
|
|
1714
|
+
if (!options?.allowTestMode) {
|
|
1715
|
+
const productError = validateProductIdentity(data.meta);
|
|
1716
|
+
if (productError) {
|
|
1717
|
+
return { valid: false, isNetworkError: false, error: productError };
|
|
1718
|
+
}
|
|
1719
|
+
}
|
|
1720
|
+
return {
|
|
1721
|
+
valid: true,
|
|
1722
|
+
licenseKey: data.license_key?.key,
|
|
1723
|
+
customerName: data.meta?.customer_name,
|
|
1724
|
+
productName: data.meta?.product_name,
|
|
1725
|
+
variantId: data.meta?.variant_id,
|
|
1726
|
+
variantName: data.meta?.variant_name
|
|
1727
|
+
};
|
|
1728
|
+
} catch (err) {
|
|
1729
|
+
const message = err instanceof Error && err.name === "AbortError" ? "Request timed out. Please check your network connection and try again." : err instanceof Error ? err.message : "Network error";
|
|
1730
|
+
return { valid: false, isNetworkError: true, error: message };
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1693
1733
|
async function deactivateLicense(licenseKey, instanceId) {
|
|
1694
1734
|
try {
|
|
1695
1735
|
const res = await fetchWithTimeout(`${BASE_URL}/deactivate`, {
|
|
@@ -1708,6 +1748,52 @@ async function deactivateLicense(licenseKey, instanceId) {
|
|
|
1708
1748
|
}
|
|
1709
1749
|
}
|
|
1710
1750
|
|
|
1751
|
+
// ../../packages/shared/src/licenseRevalidation.ts
|
|
1752
|
+
async function revalidateStaleLicenses(options) {
|
|
1753
|
+
const stale = getAllLicensesNeedingRevalidation();
|
|
1754
|
+
const result = { checked: stale.length, refreshed: 0, revoked: 0, skippedNetworkError: 0 };
|
|
1755
|
+
if (stale.length === 0) return result;
|
|
1756
|
+
const updates = /* @__PURE__ */ new Map();
|
|
1757
|
+
for (const entry of stale) {
|
|
1758
|
+
const vResult = await validateLicense(entry.licenseKey, entry.instanceId, {
|
|
1759
|
+
allowTestMode: options?.allowTestMode
|
|
1760
|
+
});
|
|
1761
|
+
if (vResult.valid) {
|
|
1762
|
+
const patch = {
|
|
1763
|
+
lastValidatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1764
|
+
};
|
|
1765
|
+
if (vResult.customerName) patch.customerName = vResult.customerName;
|
|
1766
|
+
updates.set(entry.licenseKey, patch);
|
|
1767
|
+
result.refreshed++;
|
|
1768
|
+
} else if (vResult.isNetworkError) {
|
|
1769
|
+
result.skippedNetworkError++;
|
|
1770
|
+
} else {
|
|
1771
|
+
updates.set(entry.licenseKey, { status: "inactive" });
|
|
1772
|
+
result.revoked++;
|
|
1773
|
+
}
|
|
1774
|
+
}
|
|
1775
|
+
if (updates.size > 0) {
|
|
1776
|
+
const store = readLicenseStore();
|
|
1777
|
+
for (const [key, patch] of updates) {
|
|
1778
|
+
const idx = store.licenses.findIndex((l) => l.licenseKey === key);
|
|
1779
|
+
if (idx >= 0) {
|
|
1780
|
+
Object.assign(store.licenses[idx], patch);
|
|
1781
|
+
}
|
|
1782
|
+
}
|
|
1783
|
+
writeLicenseStore(store);
|
|
1784
|
+
}
|
|
1785
|
+
return result;
|
|
1786
|
+
}
|
|
1787
|
+
async function getLicenseForFeatureWithRevalidation(feature, options) {
|
|
1788
|
+
const license = getLicenseForFeature(feature);
|
|
1789
|
+
if (!license) return void 0;
|
|
1790
|
+
if (needsRevalidation(license)) {
|
|
1791
|
+
await revalidateStaleLicenses(options);
|
|
1792
|
+
return getLicenseForFeature(feature);
|
|
1793
|
+
}
|
|
1794
|
+
return license;
|
|
1795
|
+
}
|
|
1796
|
+
|
|
1711
1797
|
// src/render.ts
|
|
1712
1798
|
var RESET = "\x1B[0m";
|
|
1713
1799
|
var BOLD = "\x1B[1m";
|
|
@@ -2023,7 +2109,7 @@ import { spawn } from "child_process";
|
|
|
2023
2109
|
import { readFileSync, existsSync } from "fs";
|
|
2024
2110
|
import path9 from "path";
|
|
2025
2111
|
import os4 from "os";
|
|
2026
|
-
var CLI_VERSION = "1.2.
|
|
2112
|
+
var CLI_VERSION = "1.2.1";
|
|
2027
2113
|
var NPM_REGISTRY_URL = "https://registry.npmjs.org/@keepgoingdev/cli/latest";
|
|
2028
2114
|
var FETCH_TIMEOUT_MS = 5e3;
|
|
2029
2115
|
var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -2743,7 +2829,7 @@ async function decisionsCommand(opts) {
|
|
|
2743
2829
|
}
|
|
2744
2830
|
return;
|
|
2745
2831
|
}
|
|
2746
|
-
if (process.env.KEEPGOING_PRO_BYPASS !== "1" && !
|
|
2832
|
+
if (process.env.KEEPGOING_PRO_BYPASS !== "1" && !await getLicenseForFeatureWithRevalidation("decisions")) {
|
|
2747
2833
|
console.error(
|
|
2748
2834
|
'Decision Detection requires a Pro license.\nRun "keepgoing activate <key>" or visit https://keepgoing.dev/add-ons to purchase.'
|
|
2749
2835
|
);
|
|
@@ -2947,8 +3033,8 @@ function renderGrouped(sessions, showStat) {
|
|
|
2947
3033
|
}
|
|
2948
3034
|
}
|
|
2949
3035
|
}
|
|
2950
|
-
function logDecisions(reader, opts) {
|
|
2951
|
-
const license =
|
|
3036
|
+
async function logDecisions(reader, opts) {
|
|
3037
|
+
const license = await getLicenseForFeatureWithRevalidation("decisions");
|
|
2952
3038
|
if (!license) {
|
|
2953
3039
|
console.log("Decision tracking requires a Pro license. Run: keepgoing activate <key>");
|
|
2954
3040
|
return;
|
|
@@ -2994,7 +3080,7 @@ async function logCommand(opts) {
|
|
|
2994
3080
|
return;
|
|
2995
3081
|
}
|
|
2996
3082
|
if (opts.subcommand === "decisions") {
|
|
2997
|
-
logDecisions(reader, opts);
|
|
3083
|
+
await logDecisions(reader, opts);
|
|
2998
3084
|
} else {
|
|
2999
3085
|
logSessions(reader, opts);
|
|
3000
3086
|
}
|
|
@@ -3477,7 +3563,7 @@ async function main() {
|
|
|
3477
3563
|
}
|
|
3478
3564
|
break;
|
|
3479
3565
|
case "version":
|
|
3480
|
-
console.log(`keepgoing v${"1.2.
|
|
3566
|
+
console.log(`keepgoing v${"1.2.1"}`);
|
|
3481
3567
|
break;
|
|
3482
3568
|
case "activate":
|
|
3483
3569
|
await activateCommand({ licenseKey: subcommand });
|