codexuse-cli 5.6.0 → 5.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +182 -67
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6228,13 +6228,20 @@ async function openLockDatabase(databasePath) {
|
|
|
6228
6228
|
throw error;
|
|
6229
6229
|
}
|
|
6230
6230
|
}
|
|
6231
|
-
async function
|
|
6231
|
+
async function acquireCrossProcessFileLockTransaction(filePath, mode) {
|
|
6232
6232
|
const databasePath = `${import_node_path8.default.resolve(filePath)}.codexuse-lock.sqlite`;
|
|
6233
6233
|
let database = null;
|
|
6234
6234
|
try {
|
|
6235
6235
|
database = await openLockDatabase(databasePath);
|
|
6236
|
+
database.exec("PRAGMA busy_timeout = 1000;");
|
|
6237
|
+
database.exec("CREATE TABLE IF NOT EXISTS codexuse_file_lock (id INTEGER PRIMARY KEY);");
|
|
6236
6238
|
database.exec("PRAGMA busy_timeout = 0;");
|
|
6237
|
-
|
|
6239
|
+
if (mode === "write") {
|
|
6240
|
+
database.exec("BEGIN EXCLUSIVE;");
|
|
6241
|
+
} else {
|
|
6242
|
+
database.exec("BEGIN;");
|
|
6243
|
+
database.exec("SELECT COUNT(*) FROM codexuse_file_lock;");
|
|
6244
|
+
}
|
|
6238
6245
|
} catch (error) {
|
|
6239
6246
|
database?.close();
|
|
6240
6247
|
if (isSqliteBusyError2(error)) {
|
|
@@ -6256,6 +6263,12 @@ async function acquireCrossProcessFileLock(filePath) {
|
|
|
6256
6263
|
}
|
|
6257
6264
|
};
|
|
6258
6265
|
}
|
|
6266
|
+
async function acquireCrossProcessFileLock(filePath) {
|
|
6267
|
+
return acquireCrossProcessFileLockTransaction(filePath, "write");
|
|
6268
|
+
}
|
|
6269
|
+
async function acquireCrossProcessFileReadLock(filePath) {
|
|
6270
|
+
return acquireCrossProcessFileLockTransaction(filePath, "read");
|
|
6271
|
+
}
|
|
6259
6272
|
|
|
6260
6273
|
// ../../packages/shared/src/core/logger.ts
|
|
6261
6274
|
var isTestEnv = process.env.NODE_ENV === "test" || process.env.VITEST === "true" || process.env.VITEST === "1";
|
|
@@ -32534,6 +32547,21 @@ async function acquireCodexAuthFileLock(filePath) {
|
|
|
32534
32547
|
throw error;
|
|
32535
32548
|
}
|
|
32536
32549
|
}
|
|
32550
|
+
async function acquireCodexAuthFileReadLock(filePath) {
|
|
32551
|
+
const queueKey = import_node_path9.default.resolve(filePath);
|
|
32552
|
+
await (authFileLockQueues.get(queueKey) ?? Promise.resolve());
|
|
32553
|
+
const releaseReadLock = await acquireCrossProcessFileReadLock(filePath);
|
|
32554
|
+
if (!releaseReadLock) {
|
|
32555
|
+
return null;
|
|
32556
|
+
}
|
|
32557
|
+
const needsRecovery = await readOptionalFile(authWritebackPaths(filePath).manifest) !== null;
|
|
32558
|
+
if (!needsRecovery) {
|
|
32559
|
+
return { mode: "read", release: releaseReadLock };
|
|
32560
|
+
}
|
|
32561
|
+
await releaseReadLock();
|
|
32562
|
+
const releaseWriteLock = await acquireCodexAuthFileLock(filePath);
|
|
32563
|
+
return releaseWriteLock ? { mode: "write", release: releaseWriteLock } : null;
|
|
32564
|
+
}
|
|
32537
32565
|
async function readAuthFileCached(filePath) {
|
|
32538
32566
|
let stats;
|
|
32539
32567
|
try {
|
|
@@ -32708,15 +32736,15 @@ async function fetchRateLimitsViaRpc(envOverride, options = {}) {
|
|
|
32708
32736
|
const tempAuthPath = import_node_path9.default.join(tempHome, "auth.json");
|
|
32709
32737
|
let initialSourceAuth;
|
|
32710
32738
|
try {
|
|
32711
|
-
const
|
|
32712
|
-
if (!
|
|
32739
|
+
const authLock = await acquireCodexAuthFileReadLock(sourceAuthPath);
|
|
32740
|
+
if (!authLock) {
|
|
32713
32741
|
await import_node_fs4.promises.rm(tempHome, { recursive: true, force: true });
|
|
32714
32742
|
return null;
|
|
32715
32743
|
}
|
|
32716
32744
|
try {
|
|
32717
32745
|
initialSourceAuth = await readAuthFileCached(sourceAuthPath);
|
|
32718
32746
|
} finally {
|
|
32719
|
-
await
|
|
32747
|
+
await authLock.release();
|
|
32720
32748
|
}
|
|
32721
32749
|
if (!initialSourceAuth) {
|
|
32722
32750
|
await import_node_fs4.promises.rm(tempHome, { recursive: true, force: true });
|
|
@@ -32843,15 +32871,15 @@ async function activateResetWindowViaRpcIsolated(envOverride, options, sourceAut
|
|
|
32843
32871
|
const tempAuthPath = import_node_path9.default.join(tempHome, "auth.json");
|
|
32844
32872
|
let initialSourceAuth;
|
|
32845
32873
|
try {
|
|
32846
|
-
const
|
|
32847
|
-
if (!
|
|
32874
|
+
const authLock = await acquireCodexAuthFileReadLock(sourceAuthPath);
|
|
32875
|
+
if (!authLock) {
|
|
32848
32876
|
await import_node_fs4.promises.rm(tempHome, { recursive: true, force: true });
|
|
32849
32877
|
return { status: "skipped", reason: "auth-busy" };
|
|
32850
32878
|
}
|
|
32851
32879
|
try {
|
|
32852
32880
|
initialSourceAuth = await readAuthFileCached(sourceAuthPath);
|
|
32853
32881
|
} finally {
|
|
32854
|
-
await
|
|
32882
|
+
await authLock.release();
|
|
32855
32883
|
}
|
|
32856
32884
|
if (!initialSourceAuth) {
|
|
32857
32885
|
await import_node_fs4.promises.rm(tempHome, { recursive: true, force: true }).catch(() => {
|
|
@@ -43081,6 +43109,7 @@ var ProfileManager = class {
|
|
|
43081
43109
|
this.jwtPayloadCache = /* @__PURE__ */ new Map();
|
|
43082
43110
|
this.profileRecordIndexCache = null;
|
|
43083
43111
|
this.credentialsMigrationPromise = null;
|
|
43112
|
+
this.blockedProfileMigrationErrors = /* @__PURE__ */ new Map();
|
|
43084
43113
|
this.profileHomeAuthSyncCache = /* @__PURE__ */ new Map();
|
|
43085
43114
|
}
|
|
43086
43115
|
computeExpiryIso(data) {
|
|
@@ -43133,6 +43162,16 @@ var ProfileManager = class {
|
|
|
43133
43162
|
normalizeProfileHomeId(value3, fallbackName) {
|
|
43134
43163
|
return normalizeProfileHomeId(value3) ?? this.normalizeProfileName(fallbackName);
|
|
43135
43164
|
}
|
|
43165
|
+
assertProfileHomeUsable(profileName) {
|
|
43166
|
+
const migrationError = this.blockedProfileMigrationErrors.get(profileName);
|
|
43167
|
+
if (!migrationError) {
|
|
43168
|
+
return;
|
|
43169
|
+
}
|
|
43170
|
+
throw errorWithCause(
|
|
43171
|
+
`Profile '${profileName}' cannot be used because another profile references the same private auth store. Delete one conflicting profile, then restart CodexUse.`,
|
|
43172
|
+
migrationError
|
|
43173
|
+
);
|
|
43174
|
+
}
|
|
43136
43175
|
isNotFoundError(error) {
|
|
43137
43176
|
return Boolean(
|
|
43138
43177
|
error && typeof error === "object" && "code" in error && error.code === "ENOENT"
|
|
@@ -43814,8 +43853,7 @@ var ProfileManager = class {
|
|
|
43814
43853
|
}
|
|
43815
43854
|
if (!this.credentialsMigrationPromise) {
|
|
43816
43855
|
this.credentialsMigrationPromise = this.migrateCredentialsToProfileHomes().catch((error) => {
|
|
43817
|
-
|
|
43818
|
-
throw error;
|
|
43856
|
+
logError("Deferred profile credential migration because the migration pass failed:", error);
|
|
43819
43857
|
});
|
|
43820
43858
|
}
|
|
43821
43859
|
await this.credentialsMigrationPromise;
|
|
@@ -43832,9 +43870,12 @@ var ProfileManager = class {
|
|
|
43832
43870
|
const collisionKey = homeId.toLowerCase();
|
|
43833
43871
|
const existingProfileName = profileNamesByHomeId.get(collisionKey);
|
|
43834
43872
|
if (existingProfileName && existingProfileName !== profileName) {
|
|
43835
|
-
|
|
43873
|
+
const collisionError = new Error(
|
|
43836
43874
|
`Profiles '${existingProfileName}' and '${profileName}' use the same private auth store. Refresh one profile before retrying.`
|
|
43837
43875
|
);
|
|
43876
|
+
this.blockedProfileMigrationErrors.set(existingProfileName, collisionError);
|
|
43877
|
+
this.blockedProfileMigrationErrors.set(profileName, collisionError);
|
|
43878
|
+
logWarn("Deferred profiles that reference the same private auth store:", collisionError);
|
|
43838
43879
|
}
|
|
43839
43880
|
homeIdsByProfileName.set(profileName, homeId);
|
|
43840
43881
|
profileNamesByHomeId.set(collisionKey, profileName);
|
|
@@ -43855,62 +43896,94 @@ var ProfileManager = class {
|
|
|
43855
43896
|
let changed = false;
|
|
43856
43897
|
const nextMap = {};
|
|
43857
43898
|
for (const [profileName, raw] of Object.entries(source)) {
|
|
43858
|
-
|
|
43859
|
-
if (!record3) {
|
|
43899
|
+
if (this.blockedProfileMigrationErrors.has(profileName)) {
|
|
43860
43900
|
nextMap[profileName] = raw;
|
|
43861
43901
|
continue;
|
|
43862
43902
|
}
|
|
43863
|
-
|
|
43864
|
-
|
|
43865
|
-
|
|
43866
|
-
|
|
43867
|
-
|
|
43868
|
-
if (needsHomeId && record3.homeId !== nextHomeId) {
|
|
43869
|
-
const sourceHome = this.getProfileHomePath(record3.homeId);
|
|
43870
|
-
const targetHome = this.getProfileHomePath(nextHomeId);
|
|
43871
|
-
let sourceExists = true;
|
|
43872
|
-
try {
|
|
43873
|
-
await import_fs.promises.access(sourceHome);
|
|
43874
|
-
} catch (error) {
|
|
43875
|
-
if (!this.isNotFoundError(error)) {
|
|
43876
|
-
throw error;
|
|
43877
|
-
}
|
|
43878
|
-
sourceExists = false;
|
|
43903
|
+
try {
|
|
43904
|
+
let record3 = this.fromStateRecord(profileName, raw);
|
|
43905
|
+
if (!record3) {
|
|
43906
|
+
nextMap[profileName] = raw;
|
|
43907
|
+
continue;
|
|
43879
43908
|
}
|
|
43880
|
-
|
|
43909
|
+
const nextHomeId = homeIdsByProfileName.get(profileName) ?? record3.homeId;
|
|
43910
|
+
const hasStateCredentials = Boolean(
|
|
43911
|
+
record3.data.id_token || record3.data.access_token || record3.data.refresh_token
|
|
43912
|
+
);
|
|
43913
|
+
const needsHomeId = normalizeProfileHomeId(raw.homeId) === null;
|
|
43914
|
+
if (needsHomeId && record3.homeId !== nextHomeId) {
|
|
43915
|
+
const sourceHome = this.getProfileHomePath(record3.homeId);
|
|
43916
|
+
const targetHome = this.getProfileHomePath(nextHomeId);
|
|
43917
|
+
let sourceExists = true;
|
|
43881
43918
|
try {
|
|
43882
|
-
await import_fs.promises.access(
|
|
43883
|
-
throw new Error(
|
|
43884
|
-
`Profile '${profileName}' cannot migrate its private auth store because the target already exists.`
|
|
43885
|
-
);
|
|
43919
|
+
await import_fs.promises.access(sourceHome);
|
|
43886
43920
|
} catch (error) {
|
|
43887
43921
|
if (!this.isNotFoundError(error)) {
|
|
43888
43922
|
throw error;
|
|
43889
43923
|
}
|
|
43924
|
+
sourceExists = false;
|
|
43890
43925
|
}
|
|
43891
|
-
|
|
43892
|
-
|
|
43893
|
-
|
|
43894
|
-
|
|
43895
|
-
|
|
43926
|
+
if (sourceExists) {
|
|
43927
|
+
let targetExists = true;
|
|
43928
|
+
try {
|
|
43929
|
+
await import_fs.promises.access(targetHome);
|
|
43930
|
+
} catch (error) {
|
|
43931
|
+
if (!this.isNotFoundError(error)) {
|
|
43932
|
+
throw error;
|
|
43933
|
+
}
|
|
43934
|
+
targetExists = false;
|
|
43935
|
+
}
|
|
43936
|
+
if (targetExists) {
|
|
43937
|
+
const sourceHydration = await this.hydrateProfileRecordWithStatus(record3);
|
|
43938
|
+
let targetAuth = null;
|
|
43939
|
+
try {
|
|
43940
|
+
const targetRaw = await this.readProfileAuthFile(
|
|
43941
|
+
(0, import_path2.join)(targetHome, "auth.json")
|
|
43942
|
+
);
|
|
43943
|
+
targetAuth = targetRaw ? JSON.parse(targetRaw) : null;
|
|
43944
|
+
} catch (error) {
|
|
43945
|
+
logWarn(
|
|
43946
|
+
`Deferred private auth migration for '${profileName}' because the existing target could not be verified:`,
|
|
43947
|
+
error
|
|
43948
|
+
);
|
|
43949
|
+
}
|
|
43950
|
+
if (!sourceHydration.cacheable || !targetAuth || !this.activeAuthMatchesRecord(targetAuth, sourceHydration.record)) {
|
|
43951
|
+
logWarn(
|
|
43952
|
+
`Deferred private auth migration for '${profileName}' because the existing target belongs to unverified credentials.`
|
|
43953
|
+
);
|
|
43954
|
+
nextMap[profileName] = raw;
|
|
43955
|
+
continue;
|
|
43956
|
+
}
|
|
43957
|
+
record3 = sourceHydration.record;
|
|
43958
|
+
} else {
|
|
43959
|
+
const releaseGuard = await this.acquireProfileHomeMutationGuard(record3);
|
|
43960
|
+
try {
|
|
43961
|
+
await import_fs.promises.rename(sourceHome, targetHome);
|
|
43962
|
+
} finally {
|
|
43963
|
+
await releaseGuard();
|
|
43964
|
+
}
|
|
43965
|
+
}
|
|
43896
43966
|
}
|
|
43897
43967
|
}
|
|
43898
|
-
|
|
43899
|
-
|
|
43900
|
-
|
|
43901
|
-
|
|
43902
|
-
|
|
43903
|
-
|
|
43904
|
-
|
|
43905
|
-
|
|
43906
|
-
|
|
43968
|
+
record3.homeId = nextHomeId;
|
|
43969
|
+
if (!hasStateCredentials && !needsHomeId && raw.credentialsSource === "profile-home") {
|
|
43970
|
+
nextMap[profileName] = raw;
|
|
43971
|
+
continue;
|
|
43972
|
+
}
|
|
43973
|
+
const hydration = await this.hydrateProfileRecordWithStatus(record3);
|
|
43974
|
+
if (!hasStateCredentials && !hydration.cacheable) {
|
|
43975
|
+
nextMap[profileName] = this.toStateRecord(record3);
|
|
43976
|
+
changed = true;
|
|
43977
|
+
continue;
|
|
43978
|
+
}
|
|
43979
|
+
nextMap[profileName] = this.toStateRecord(
|
|
43980
|
+
await this.hydrateProfileRecordStrict(hydration.record)
|
|
43981
|
+
);
|
|
43907
43982
|
changed = true;
|
|
43908
|
-
|
|
43983
|
+
} catch (error) {
|
|
43984
|
+
nextMap[profileName] = raw;
|
|
43985
|
+
logWarn(`Deferred private auth migration for '${profileName}':`, error);
|
|
43909
43986
|
}
|
|
43910
|
-
nextMap[profileName] = this.toStateRecord(
|
|
43911
|
-
await this.hydrateProfileRecordStrict(hydration.record)
|
|
43912
|
-
);
|
|
43913
|
-
changed = true;
|
|
43914
43987
|
}
|
|
43915
43988
|
if (changed) {
|
|
43916
43989
|
this.profileRecordIndexCache = null;
|
|
@@ -44183,6 +44256,48 @@ var ProfileManager = class {
|
|
|
44183
44256
|
}
|
|
44184
44257
|
return result2;
|
|
44185
44258
|
}
|
|
44259
|
+
async readProfileAuthFile(authPath) {
|
|
44260
|
+
const authLock = await acquireCodexAuthFileReadLock(authPath);
|
|
44261
|
+
if (!authLock) {
|
|
44262
|
+
throw profileMutationError(
|
|
44263
|
+
"PROFILE_HOME_BUSY",
|
|
44264
|
+
"Another CodexUse process is updating this profile auth. Retry after it finishes."
|
|
44265
|
+
);
|
|
44266
|
+
}
|
|
44267
|
+
let result2 = null;
|
|
44268
|
+
let readError = null;
|
|
44269
|
+
let needsWriteRecovery = false;
|
|
44270
|
+
try {
|
|
44271
|
+
const recoveryManifest = await this.readOptionalFile(
|
|
44272
|
+
this.profileAuthCasPaths(authPath).manifest
|
|
44273
|
+
);
|
|
44274
|
+
if (recoveryManifest !== null && authLock.mode === "read") {
|
|
44275
|
+
needsWriteRecovery = true;
|
|
44276
|
+
} else {
|
|
44277
|
+
if (recoveryManifest !== null) {
|
|
44278
|
+
await this.recoverProfileAuthCasIfNeeded(authPath);
|
|
44279
|
+
}
|
|
44280
|
+
result2 = await this.readOptionalFile(authPath);
|
|
44281
|
+
}
|
|
44282
|
+
} catch (error) {
|
|
44283
|
+
readError = error;
|
|
44284
|
+
}
|
|
44285
|
+
try {
|
|
44286
|
+
await authLock.release();
|
|
44287
|
+
} catch (releaseError) {
|
|
44288
|
+
throw errorWithCause("Profile auth read lock could not be released.", {
|
|
44289
|
+
readError,
|
|
44290
|
+
releaseError
|
|
44291
|
+
});
|
|
44292
|
+
}
|
|
44293
|
+
if (readError) {
|
|
44294
|
+
throw readError;
|
|
44295
|
+
}
|
|
44296
|
+
if (needsWriteRecovery) {
|
|
44297
|
+
return this.withProfileAuthFileLock(authPath, async (currentRaw) => currentRaw);
|
|
44298
|
+
}
|
|
44299
|
+
return result2;
|
|
44300
|
+
}
|
|
44186
44301
|
async replaceProfileAuthIfCurrent(authPath, expectedRaw, replacementRaw) {
|
|
44187
44302
|
await this.withProfileAuthFileLock(authPath, async (currentRaw) => {
|
|
44188
44303
|
if (currentRaw !== expectedRaw) {
|
|
@@ -44518,13 +44633,14 @@ var ProfileManager = class {
|
|
|
44518
44633
|
return (await this.hydrateProfileRecordWithStatus(record3)).record;
|
|
44519
44634
|
}
|
|
44520
44635
|
async hydrateProfileRecordWithStatus(record3) {
|
|
44636
|
+
const migrationError = this.blockedProfileMigrationErrors.get(record3.name);
|
|
44637
|
+
if (migrationError) {
|
|
44638
|
+
return { record: record3, cacheable: false };
|
|
44639
|
+
}
|
|
44521
44640
|
const authPath = import_path.default.join(this.getProfileHomePath(record3.homeId), "auth.json");
|
|
44522
44641
|
let authRaw;
|
|
44523
44642
|
try {
|
|
44524
|
-
const recovered = await this.
|
|
44525
|
-
authPath,
|
|
44526
|
-
async (currentRaw) => currentRaw
|
|
44527
|
-
);
|
|
44643
|
+
const recovered = await this.readProfileAuthFile(authPath);
|
|
44528
44644
|
if (recovered === null) {
|
|
44529
44645
|
const missing = new Error("Profile auth is missing.");
|
|
44530
44646
|
missing.code = "ENOENT";
|
|
@@ -44627,18 +44743,14 @@ var ProfileManager = class {
|
|
|
44627
44743
|
};
|
|
44628
44744
|
}
|
|
44629
44745
|
async hydrateProfileRecordStrict(record3) {
|
|
44746
|
+
this.assertProfileHomeUsable(record3.name);
|
|
44630
44747
|
const authPath = import_path.default.join(this.getProfileHomePath(record3.homeId), "auth.json");
|
|
44631
44748
|
let activeAuth;
|
|
44632
44749
|
try {
|
|
44633
|
-
const raw = await this.
|
|
44634
|
-
|
|
44635
|
-
|
|
44636
|
-
|
|
44637
|
-
throw new Error("Profile auth is missing.");
|
|
44638
|
-
}
|
|
44639
|
-
return currentRaw;
|
|
44640
|
-
}
|
|
44641
|
-
);
|
|
44750
|
+
const raw = await this.readProfileAuthFile(authPath);
|
|
44751
|
+
if (raw === null) {
|
|
44752
|
+
throw new Error("Profile auth is missing.");
|
|
44753
|
+
}
|
|
44642
44754
|
activeAuth = JSON.parse(raw);
|
|
44643
44755
|
} catch (error) {
|
|
44644
44756
|
throw errorWithCause(
|
|
@@ -44730,6 +44842,7 @@ var ProfileManager = class {
|
|
|
44730
44842
|
return activeDescription.identityKey === targetIdentity && this.normalizeWorkspaceId(activeDescription.workspaceId) === targetWorkspaceId;
|
|
44731
44843
|
}
|
|
44732
44844
|
async writeActiveAuthForRecordLocked(record3, expectedSourceFingerprint) {
|
|
44845
|
+
this.assertProfileHomeUsable(record3.name);
|
|
44733
44846
|
const releaseIntent = await this.acquireProfileHomeWriteIntent(record3);
|
|
44734
44847
|
try {
|
|
44735
44848
|
const latest = await this.readStoredProfileRecord(record3.name);
|
|
@@ -45026,6 +45139,7 @@ var ProfileManager = class {
|
|
|
45026
45139
|
}
|
|
45027
45140
|
async persistProfileRecord(name, data, metadata, options) {
|
|
45028
45141
|
const resolvedName = this.normalizeProfileName(name);
|
|
45142
|
+
this.assertProfileHomeUsable(resolvedName);
|
|
45029
45143
|
const initialMap = await this.readProfilesStateMap();
|
|
45030
45144
|
const initialState = initialMap[resolvedName] ?? null;
|
|
45031
45145
|
const storedExisting = initialState ? this.fromStateRecord(resolvedName, initialState) : null;
|
|
@@ -46651,6 +46765,7 @@ var ProfileManager = class {
|
|
|
46651
46765
|
await this.initialize();
|
|
46652
46766
|
const sourceName = this.normalizeProfileName(oldName);
|
|
46653
46767
|
const targetName = this.normalizeProfileName(newName);
|
|
46768
|
+
this.assertProfileHomeUsable(sourceName);
|
|
46654
46769
|
const initialProfiles = await this.readProfilesStateMap();
|
|
46655
46770
|
const expectedSourceState = initialProfiles[sourceName] ?? null;
|
|
46656
46771
|
const existing = expectedSourceState ? this.fromStateRecord(sourceName, expectedSourceState) : null;
|
|
@@ -51673,7 +51788,7 @@ async function ensureCliStorageReady() {
|
|
|
51673
51788
|
}
|
|
51674
51789
|
|
|
51675
51790
|
// src/app/main.ts
|
|
51676
|
-
var VERSION = true ? "5.6.
|
|
51791
|
+
var VERSION = true ? "5.6.2" : "0.0.0";
|
|
51677
51792
|
async function runCli() {
|
|
51678
51793
|
const args2 = process.argv.slice(2);
|
|
51679
51794
|
if (args2.length === 0) {
|