@neopress/cli 4.1.0 → 4.2.0

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.
Files changed (3) hide show
  1. package/dist/bin.cjs +110 -58
  2. package/dist/index.js +77 -44
  3. package/package.json +1 -1
package/dist/bin.cjs CHANGED
@@ -3387,6 +3387,7 @@ function fail(message, code = 1) {
3387
3387
  // src/utils/config.ts
3388
3388
  var import_node_fs2 = require("fs");
3389
3389
  var import_node_path2 = require("path");
3390
+ var import_node_os2 = require("os");
3390
3391
 
3391
3392
  // src/utils/token-store.ts
3392
3393
  var import_node_fs = require("fs");
@@ -3421,31 +3422,55 @@ function clearSession() {
3421
3422
  // src/utils/config.ts
3422
3423
  var PROJECT_CONFIG = ".neopressrc.json";
3423
3424
  var WORKSPACE_CONFIG = ".neopress/config.json";
3424
- function readProjectConfig() {
3425
- let config2 = {};
3426
- for (const file2 of [PROJECT_CONFIG, WORKSPACE_CONFIG]) {
3427
- try {
3428
- const parsed = JSON.parse((0, import_node_fs2.readFileSync)(file2, "utf-8"));
3429
- config2 = {
3430
- ...config2,
3431
- ...typeof parsed.siteId === "number" ? { siteId: parsed.siteId } : {},
3432
- ...typeof parsed.baseUrl === "string" ? { baseUrl: parsed.baseUrl } : {}
3433
- };
3434
- } catch {
3425
+ function readConfigFileAt(path) {
3426
+ try {
3427
+ const parsed = JSON.parse((0, import_node_fs2.readFileSync)(path, "utf-8"));
3428
+ return {
3429
+ ...typeof parsed.siteId === "number" ? { siteId: parsed.siteId } : {},
3430
+ ...typeof parsed.baseUrl === "string" ? { baseUrl: parsed.baseUrl } : {}
3431
+ };
3432
+ } catch {
3433
+ return {};
3434
+ }
3435
+ }
3436
+ function locateProjectConfig(startDir = process.cwd()) {
3437
+ const home = (0, import_node_path2.resolve)((0, import_node_os2.homedir)());
3438
+ let dir = (0, import_node_path2.resolve)(startDir);
3439
+ while (true) {
3440
+ let merged = {};
3441
+ let foundPath;
3442
+ for (const rel of [PROJECT_CONFIG, WORKSPACE_CONFIG]) {
3443
+ const p = (0, import_node_path2.join)(dir, rel);
3444
+ const cfg = readConfigFileAt(p);
3445
+ if (Object.keys(cfg).length > 0) {
3446
+ merged = { ...merged, ...cfg };
3447
+ if (!foundPath) foundPath = p;
3448
+ }
3435
3449
  }
3450
+ if (Object.keys(merged).length > 0) return { config: merged, path: foundPath };
3451
+ const parent = (0, import_node_path2.dirname)(dir);
3452
+ if (dir === home || parent === dir) break;
3453
+ dir = parent;
3436
3454
  }
3437
- return config2;
3455
+ return { config: {} };
3456
+ }
3457
+ function readProjectConfig() {
3458
+ return locateProjectConfig().config;
3438
3459
  }
3439
3460
  function writeWorkspaceConfig(next) {
3440
3461
  (0, import_node_fs2.mkdirSync)((0, import_node_path2.dirname)(WORKSPACE_CONFIG), { recursive: true });
3441
3462
  (0, import_node_fs2.writeFileSync)(WORKSPACE_CONFIG, JSON.stringify(next, null, 2) + "\n", "utf-8");
3442
3463
  }
3443
- function getSiteId() {
3444
- const envSiteId = process.env.NEOPRESS_SITE_ID;
3445
- if (envSiteId) return parseInt(envSiteId, 10);
3446
- const projectConfig = readProjectConfig();
3447
- if (projectConfig.siteId) return projectConfig.siteId;
3448
- return loadSession().activeSiteId;
3464
+ function writeProjectSiteId(siteId) {
3465
+ let raw = {};
3466
+ try {
3467
+ const parsed = JSON.parse((0, import_node_fs2.readFileSync)(PROJECT_CONFIG, "utf-8"));
3468
+ if (parsed && typeof parsed === "object") raw = parsed;
3469
+ } catch {
3470
+ }
3471
+ const next = { ...raw, siteId };
3472
+ (0, import_node_fs2.writeFileSync)(PROJECT_CONFIG, JSON.stringify(next, null, 2) + "\n", "utf-8");
3473
+ return (0, import_node_path2.resolve)(PROJECT_CONFIG);
3449
3474
  }
3450
3475
  function getBaseUrl() {
3451
3476
  return process.env.NEOPRESS_BASE_URL || readProjectConfig().baseUrl || "https://app.neopress.ai";
@@ -3461,12 +3486,24 @@ var siteOverride;
3461
3486
  function setSiteOverride(value) {
3462
3487
  siteOverride = value;
3463
3488
  }
3464
- function getSiteTarget() {
3489
+ function resolveSiteTarget() {
3465
3490
  if (siteOverride) {
3466
3491
  const n = parseInt(siteOverride, 10);
3467
- return String(n) === siteOverride ? n : siteOverride;
3492
+ const value = String(n) === siteOverride ? n : siteOverride;
3493
+ return { value, source: "flag", detail: "--site" };
3494
+ }
3495
+ const envSiteId = process.env.NEOPRESS_SITE_ID;
3496
+ if (envSiteId) return { value: parseInt(envSiteId, 10), source: "env", detail: "NEOPRESS_SITE_ID" };
3497
+ const located = locateProjectConfig();
3498
+ if (typeof located.config.siteId === "number") {
3499
+ return { value: located.config.siteId, source: "project-config", detail: located.path };
3468
3500
  }
3469
- return getSiteId();
3501
+ const active = loadSession().activeSiteId;
3502
+ if (active) return { value: active, source: "global-active", detail: "sites use" };
3503
+ return { value: void 0, source: "none" };
3504
+ }
3505
+ function getSiteTarget() {
3506
+ return resolveSiteTarget().value;
3470
3507
  }
3471
3508
 
3472
3509
  // src/utils/pkce.ts
@@ -3759,11 +3796,11 @@ function __rest(s, e) {
3759
3796
  }
3760
3797
  function __awaiter(thisArg, _arguments, P, generator) {
3761
3798
  function adopt(value) {
3762
- return value instanceof P ? value : new P(function(resolve) {
3763
- resolve(value);
3799
+ return value instanceof P ? value : new P(function(resolve2) {
3800
+ resolve2(value);
3764
3801
  });
3765
3802
  }
3766
- return new (P || (P = Promise))(function(resolve, reject) {
3803
+ return new (P || (P = Promise))(function(resolve2, reject) {
3767
3804
  function fulfilled(value) {
3768
3805
  try {
3769
3806
  step(generator.next(value));
@@ -3779,7 +3816,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
3779
3816
  }
3780
3817
  }
3781
3818
  function step(result) {
3782
- result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
3819
+ result.done ? resolve2(result.value) : adopt(result.value).then(fulfilled, rejected);
3783
3820
  }
3784
3821
  step((generator = generator.apply(thisArg, _arguments || [])).next());
3785
3822
  });
@@ -4150,18 +4187,18 @@ var PostgrestError = class extends Error {
4150
4187
  }
4151
4188
  };
4152
4189
  function sleep(ms, signal) {
4153
- return new Promise((resolve) => {
4190
+ return new Promise((resolve2) => {
4154
4191
  if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
4155
- resolve();
4192
+ resolve2();
4156
4193
  return;
4157
4194
  }
4158
4195
  const id = setTimeout(() => {
4159
4196
  signal === null || signal === void 0 || signal.removeEventListener("abort", onAbort);
4160
- resolve();
4197
+ resolve2();
4161
4198
  }, ms);
4162
4199
  function onAbort() {
4163
4200
  clearTimeout(id);
4164
- resolve();
4201
+ resolve2();
4165
4202
  }
4166
4203
  signal === null || signal === void 0 || signal.addEventListener("abort", onAbort);
4167
4204
  });
@@ -12110,15 +12147,15 @@ var RealtimeChannel = class _RealtimeChannel {
12110
12147
  }
12111
12148
  }
12112
12149
  } else {
12113
- return new Promise((resolve) => {
12150
+ return new Promise((resolve2) => {
12114
12151
  var _a3, _b2, _c;
12115
12152
  const push = this.channelAdapter.push(args.type, args, opts.timeout || this.timeout);
12116
12153
  if (args.type === "broadcast" && !((_c = (_b2 = (_a3 = this.params) === null || _a3 === void 0 ? void 0 : _a3.config) === null || _b2 === void 0 ? void 0 : _b2.broadcast) === null || _c === void 0 ? void 0 : _c.ack)) {
12117
- resolve("ok");
12154
+ resolve2("ok");
12118
12155
  }
12119
- push.receive("ok", () => resolve("ok"));
12120
- push.receive("error", () => resolve("error"));
12121
- push.receive("timeout", () => resolve("timed out"));
12156
+ push.receive("ok", () => resolve2("ok"));
12157
+ push.receive("error", () => resolve2("error"));
12158
+ push.receive("timeout", () => resolve2("timed out"));
12122
12159
  });
12123
12160
  }
12124
12161
  }
@@ -12143,8 +12180,8 @@ var RealtimeChannel = class _RealtimeChannel {
12143
12180
  * @category Realtime
12144
12181
  */
12145
12182
  async unsubscribe(timeout = this.timeout) {
12146
- return new Promise((resolve) => {
12147
- this.channelAdapter.unsubscribe(timeout).receive("ok", () => resolve("ok")).receive("timeout", () => resolve("timed out")).receive("error", () => resolve("error"));
12183
+ return new Promise((resolve2) => {
12184
+ this.channelAdapter.unsubscribe(timeout).receive("ok", () => resolve2("ok")).receive("timeout", () => resolve2("timed out")).receive("error", () => resolve2("error"));
12148
12185
  });
12149
12186
  }
12150
12187
  /**
@@ -12225,8 +12262,8 @@ var RealtimeChannel = class _RealtimeChannel {
12225
12262
  }
12226
12263
  /** @internal */
12227
12264
  _notThisChannelEvent(event, ref) {
12228
- const { close, error: error48, leave, join: join2 } = CHANNEL_EVENTS;
12229
- const events = [close, error48, leave, join2];
12265
+ const { close, error: error48, leave, join: join3 } = CHANNEL_EVENTS;
12266
+ const events = [close, error48, leave, join3];
12230
12267
  return ref && events.includes(event) && ref !== this.joinPush.ref;
12231
12268
  }
12232
12269
  /** @internal */
@@ -12339,11 +12376,11 @@ var SocketAdapter = class {
12339
12376
  this.socket.connect();
12340
12377
  }
12341
12378
  disconnect(callback, code, reason, timeout = 1e4) {
12342
- return new Promise((resolve) => {
12343
- setTimeout(() => resolve("timeout"), timeout);
12379
+ return new Promise((resolve2) => {
12380
+ setTimeout(() => resolve2("timeout"), timeout);
12344
12381
  this.socket.disconnect(() => {
12345
12382
  callback();
12346
- resolve("ok");
12383
+ resolve2("ok");
12347
12384
  }, code, reason);
12348
12385
  });
12349
12386
  }
@@ -13757,7 +13794,7 @@ var _getRequestParams = (method, options, parameters, body) => {
13757
13794
  return _objectSpread22(_objectSpread22({}, params), parameters);
13758
13795
  };
13759
13796
  async function _handleRequest(fetcher, method, url2, options, parameters, body, namespace) {
13760
- return new Promise((resolve, reject) => {
13797
+ return new Promise((resolve2, reject) => {
13761
13798
  fetcher(url2, _getRequestParams(method, options, parameters, body)).then((result) => {
13762
13799
  if (!result.ok) throw result;
13763
13800
  if (options === null || options === void 0 ? void 0 : options.noResolveJson) return result;
@@ -13767,7 +13804,7 @@ async function _handleRequest(fetcher, method, url2, options, parameters, body,
13767
13804
  if (!contentType || !contentType.includes("application/json")) return {};
13768
13805
  }
13769
13806
  return result.json();
13770
- }).then((data) => resolve(data)).catch((error48) => handleError(error48, reject, options, namespace));
13807
+ }).then((data) => resolve2(data)).catch((error48) => handleError(error48, reject, options, namespace));
13771
13808
  });
13772
13809
  }
13773
13810
  function createFetchApi(namespace = "storage") {
@@ -24012,11 +24049,11 @@ var DEFAULT_TRACE_PROPAGATION_OPTIONS = {
24012
24049
  };
24013
24050
  function __awaiter2(thisArg, _arguments, P, generator) {
24014
24051
  function adopt(value) {
24015
- return value instanceof P ? value : new P(function(resolve) {
24016
- resolve(value);
24052
+ return value instanceof P ? value : new P(function(resolve2) {
24053
+ resolve2(value);
24017
24054
  });
24018
24055
  }
24019
- return new (P || (P = Promise))(function(resolve, reject) {
24056
+ return new (P || (P = Promise))(function(resolve2, reject) {
24020
24057
  function fulfilled(value) {
24021
24058
  try {
24022
24059
  step(generator.next(value));
@@ -24032,7 +24069,7 @@ function __awaiter2(thisArg, _arguments, P, generator) {
24032
24069
  }
24033
24070
  }
24034
24071
  function step(result) {
24035
- result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
24072
+ result.done ? resolve2(result.value) : adopt(result.value).then(fulfilled, rejected);
24036
24073
  }
24037
24074
  step((generator = generator.apply(thisArg, _arguments || [])).next());
24038
24075
  });
@@ -39254,8 +39291,8 @@ var SiteHistoryService = class _SiteHistoryService {
39254
39291
  const previousLock = _SiteHistoryService.sessionLocks.get(key) ?? Promise.resolve();
39255
39292
  let releaseCurrentLock = () => {
39256
39293
  };
39257
- const currentLock = new Promise((resolve) => {
39258
- releaseCurrentLock = resolve;
39294
+ const currentLock = new Promise((resolve2) => {
39295
+ releaseCurrentLock = resolve2;
39259
39296
  });
39260
39297
  const queuedLock = previousLock.catch(() => {
39261
39298
  }).then(() => currentLock);
@@ -40881,8 +40918,10 @@ function registerSiteCommands(program3) {
40881
40918
  Examples:
40882
40919
  $ neopress sites list
40883
40920
  $ neopress sites create --name "My Site" --handle my-site --use
40921
+ $ neopress sites create --name "My Site" --handle my-site --pin
40884
40922
  $ neopress sites use my-site
40885
- Run \`sites use <id|handle>\` to set the active site for all other commands.`);
40923
+ $ neopress sites current
40924
+ Run \`sites use <id|handle>\` to set the global active site, or \`sites create --pin\` to scope a site to the current directory. \`sites current\` shows which site commands will target and why.`);
40886
40925
  sites.command("list").description("List accessible sites").action(async () => {
40887
40926
  const client = await getGlobalClientAsync();
40888
40927
  const sitesList = await client.site.list();
@@ -40913,10 +40952,14 @@ Examples:
40913
40952
  $ neopress sites create --name "My Site" --handle my-site
40914
40953
  $ neopress sites create --prompt "a portfolio for a freelance photographer" --use
40915
40954
  $ neopress sites create --name Acme --handle acme --language en
40916
- Pass --prompt to auto-generate name/handle, or supply both --name and --handle. --language sets the default content locale (default en). --use sets the new site as active.`).option("--name <name>", "Site name").option("--handle <handle>", "Site handle").option("--prompt <prompt>", "Prompt to generate site name/handle").option("--language <locale>", "Default content locale", "en").option("--use", "Set the created site as active").action(async (options) => {
40955
+ Pass --prompt to auto-generate name/handle, or supply both --name and --handle. --language sets the default content locale (default en).
40956
+ --use sets the new site as the GLOBAL active site (shared across all directories). --pin instead writes ./.neopressrc.json for THIS directory only, leaving the global active site untouched \u2014 prefer it for parallel/automated runs so concurrent builds don't stomp each other's active site.`).option("--name <name>", "Site name").option("--handle <handle>", "Site handle").option("--prompt <prompt>", "Prompt to generate site name/handle").option("--language <locale>", "Default content locale", "en").option("--use", "Set the created site as the global active site").option("--pin", "Pin the created site to this directory via ./.neopressrc.json (no global state)").action(async (options) => {
40917
40957
  if (!options.prompt && !(options.name && options.handle)) {
40918
40958
  fail("Provide --prompt or both --name and --handle.");
40919
40959
  }
40960
+ if (options.use && options.pin) {
40961
+ fail("Pass only one of --use (global active site) or --pin (this directory only).");
40962
+ }
40920
40963
  const client = await getGlobalClientAsync();
40921
40964
  const site = await client.site.create({
40922
40965
  siteName: options.name,
@@ -40924,17 +40967,26 @@ Pass --prompt to auto-generate name/handle, or supply both --name and --handle.
40924
40967
  prompt: options.prompt,
40925
40968
  language: options.language
40926
40969
  });
40927
- if (options.use) {
40928
- setActiveSiteId(site.id);
40929
- }
40970
+ if (options.use) setActiveSiteId(site.id);
40971
+ let pinnedPath;
40972
+ if (options.pin) pinnedPath = writeProjectSiteId(site.id);
40930
40973
  output(site);
40931
- if (options.use && !isJsonMode()) ok(`Active site set to ${site.id}`);
40974
+ if (!isJsonMode()) {
40975
+ if (options.use) ok(`Active site set to ${site.id}`);
40976
+ if (options.pin) ok(`Pinned site ${site.id} for this directory (${pinnedPath})`);
40977
+ }
40932
40978
  });
40933
40979
  sites.command("get").description("Get current site info").action(async () => {
40934
40980
  const client = await getClientAsync();
40935
40981
  const site = await client.site.get();
40936
40982
  output(site);
40937
40983
  });
40984
+ sites.command("current").description("Show which site commands will target, and where it resolved from").addHelpText("after", `
40985
+ Resolution order: --site flag > NEOPRESS_SITE_ID > .neopressrc.json/.neopress/config.json (cwd and up) > global active site (set by \`sites use\`).
40986
+ Local check only \u2014 it does not contact the server. Unlike \`whoami\` (which always reports the global active site), this reports the site your next command will actually hit.`).action(() => {
40987
+ const { value, source, detail } = resolveSiteTarget();
40988
+ output({ siteId: value ?? null, source, resolvedFrom: detail ?? null });
40989
+ });
40938
40990
  sites.command("update").description("Update site settings").addHelpText("after", `
40939
40991
  Examples:
40940
40992
  $ neopress sites update --name "New Name"
@@ -40969,9 +41021,9 @@ Permanently deletes the site and all its content (workspace admin only) \u2014 t
40969
41021
  const { createInterface } = await import("readline");
40970
41022
  const rl = createInterface({ input: process.stdin, output: process.stdout });
40971
41023
  const answer = await new Promise(
40972
- (resolve) => rl.question(`Delete site "${siteIdOrHandle}" and ALL its content? Type the id/handle to confirm: `, (a) => {
41024
+ (resolve2) => rl.question(`Delete site "${siteIdOrHandle}" and ALL its content? Type the id/handle to confirm: `, (a) => {
40973
41025
  rl.close();
40974
- resolve(a.trim());
41026
+ resolve2(a.trim());
40975
41027
  })
40976
41028
  );
40977
41029
  if (answer !== siteIdOrHandle) {
@@ -41945,7 +41997,7 @@ function registerGuideCommands(program3) {
41945
41997
 
41946
41998
  // src/bin.ts
41947
41999
  var program2 = new Command();
41948
- program2.name("neopress").description("Neopress CLI \u2014 manage your site from the terminal").version("4.1.0").option("--json", "Output in JSON format (for AI tools and pipes)").option("--site <idOrHandle>", "Target a specific site (overrides active site; not persisted)").option("--no-input", "Non-interactive mode").hook("preAction", (thisCommand) => {
42000
+ program2.name("neopress").description("Neopress CLI \u2014 manage your site from the terminal").version("4.2.0").option("--json", "Output in JSON format (for AI tools and pipes)").option("--site <idOrHandle>", "Target a specific site (overrides active site; not persisted)").option("--no-input", "Non-interactive mode").hook("preAction", (thisCommand) => {
41949
42001
  const opts = thisCommand.optsWithGlobals();
41950
42002
  if (opts.site) setSiteOverride(String(opts.site));
41951
42003
  if (opts.json || !process.stdout.isTTY) setJsonMode(true);
package/dist/index.js CHANGED
@@ -18,11 +18,11 @@ function __rest(s, e) {
18
18
  }
19
19
  function __awaiter(thisArg, _arguments, P, generator) {
20
20
  function adopt(value) {
21
- return value instanceof P ? value : new P(function(resolve) {
22
- resolve(value);
21
+ return value instanceof P ? value : new P(function(resolve2) {
22
+ resolve2(value);
23
23
  });
24
24
  }
25
- return new (P || (P = Promise))(function(resolve, reject) {
25
+ return new (P || (P = Promise))(function(resolve2, reject) {
26
26
  function fulfilled(value) {
27
27
  try {
28
28
  step(generator.next(value));
@@ -38,7 +38,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
38
38
  }
39
39
  }
40
40
  function step(result) {
41
- result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
41
+ result.done ? resolve2(result.value) : adopt(result.value).then(fulfilled, rejected);
42
42
  }
43
43
  step((generator = generator.apply(thisArg, _arguments || [])).next());
44
44
  });
@@ -409,18 +409,18 @@ var PostgrestError = class extends Error {
409
409
  }
410
410
  };
411
411
  function sleep(ms, signal) {
412
- return new Promise((resolve) => {
412
+ return new Promise((resolve2) => {
413
413
  if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
414
- resolve();
414
+ resolve2();
415
415
  return;
416
416
  }
417
417
  const id = setTimeout(() => {
418
418
  signal === null || signal === void 0 || signal.removeEventListener("abort", onAbort);
419
- resolve();
419
+ resolve2();
420
420
  }, ms);
421
421
  function onAbort() {
422
422
  clearTimeout(id);
423
- resolve();
423
+ resolve2();
424
424
  }
425
425
  signal === null || signal === void 0 || signal.addEventListener("abort", onAbort);
426
426
  });
@@ -8369,15 +8369,15 @@ var RealtimeChannel = class _RealtimeChannel {
8369
8369
  }
8370
8370
  }
8371
8371
  } else {
8372
- return new Promise((resolve) => {
8372
+ return new Promise((resolve2) => {
8373
8373
  var _a3, _b2, _c;
8374
8374
  const push = this.channelAdapter.push(args.type, args, opts.timeout || this.timeout);
8375
8375
  if (args.type === "broadcast" && !((_c = (_b2 = (_a3 = this.params) === null || _a3 === void 0 ? void 0 : _a3.config) === null || _b2 === void 0 ? void 0 : _b2.broadcast) === null || _c === void 0 ? void 0 : _c.ack)) {
8376
- resolve("ok");
8376
+ resolve2("ok");
8377
8377
  }
8378
- push.receive("ok", () => resolve("ok"));
8379
- push.receive("error", () => resolve("error"));
8380
- push.receive("timeout", () => resolve("timed out"));
8378
+ push.receive("ok", () => resolve2("ok"));
8379
+ push.receive("error", () => resolve2("error"));
8380
+ push.receive("timeout", () => resolve2("timed out"));
8381
8381
  });
8382
8382
  }
8383
8383
  }
@@ -8402,8 +8402,8 @@ var RealtimeChannel = class _RealtimeChannel {
8402
8402
  * @category Realtime
8403
8403
  */
8404
8404
  async unsubscribe(timeout = this.timeout) {
8405
- return new Promise((resolve) => {
8406
- this.channelAdapter.unsubscribe(timeout).receive("ok", () => resolve("ok")).receive("timeout", () => resolve("timed out")).receive("error", () => resolve("error"));
8405
+ return new Promise((resolve2) => {
8406
+ this.channelAdapter.unsubscribe(timeout).receive("ok", () => resolve2("ok")).receive("timeout", () => resolve2("timed out")).receive("error", () => resolve2("error"));
8407
8407
  });
8408
8408
  }
8409
8409
  /**
@@ -8484,8 +8484,8 @@ var RealtimeChannel = class _RealtimeChannel {
8484
8484
  }
8485
8485
  /** @internal */
8486
8486
  _notThisChannelEvent(event, ref) {
8487
- const { close, error: error48, leave, join: join2 } = CHANNEL_EVENTS;
8488
- const events = [close, error48, leave, join2];
8487
+ const { close, error: error48, leave, join: join3 } = CHANNEL_EVENTS;
8488
+ const events = [close, error48, leave, join3];
8489
8489
  return ref && events.includes(event) && ref !== this.joinPush.ref;
8490
8490
  }
8491
8491
  /** @internal */
@@ -8598,11 +8598,11 @@ var SocketAdapter = class {
8598
8598
  this.socket.connect();
8599
8599
  }
8600
8600
  disconnect(callback, code, reason, timeout = 1e4) {
8601
- return new Promise((resolve) => {
8602
- setTimeout(() => resolve("timeout"), timeout);
8601
+ return new Promise((resolve2) => {
8602
+ setTimeout(() => resolve2("timeout"), timeout);
8603
8603
  this.socket.disconnect(() => {
8604
8604
  callback();
8605
- resolve("ok");
8605
+ resolve2("ok");
8606
8606
  }, code, reason);
8607
8607
  });
8608
8608
  }
@@ -10016,7 +10016,7 @@ var _getRequestParams = (method, options, parameters, body) => {
10016
10016
  return _objectSpread22(_objectSpread22({}, params), parameters);
10017
10017
  };
10018
10018
  async function _handleRequest(fetcher, method, url2, options, parameters, body, namespace) {
10019
- return new Promise((resolve, reject) => {
10019
+ return new Promise((resolve2, reject) => {
10020
10020
  fetcher(url2, _getRequestParams(method, options, parameters, body)).then((result) => {
10021
10021
  if (!result.ok) throw result;
10022
10022
  if (options === null || options === void 0 ? void 0 : options.noResolveJson) return result;
@@ -10026,7 +10026,7 @@ async function _handleRequest(fetcher, method, url2, options, parameters, body,
10026
10026
  if (!contentType || !contentType.includes("application/json")) return {};
10027
10027
  }
10028
10028
  return result.json();
10029
- }).then((data) => resolve(data)).catch((error48) => handleError(error48, reject, options, namespace));
10029
+ }).then((data) => resolve2(data)).catch((error48) => handleError(error48, reject, options, namespace));
10030
10030
  });
10031
10031
  }
10032
10032
  function createFetchApi(namespace = "storage") {
@@ -20271,11 +20271,11 @@ var DEFAULT_TRACE_PROPAGATION_OPTIONS = {
20271
20271
  };
20272
20272
  function __awaiter2(thisArg, _arguments, P, generator) {
20273
20273
  function adopt(value) {
20274
- return value instanceof P ? value : new P(function(resolve) {
20275
- resolve(value);
20274
+ return value instanceof P ? value : new P(function(resolve2) {
20275
+ resolve2(value);
20276
20276
  });
20277
20277
  }
20278
- return new (P || (P = Promise))(function(resolve, reject) {
20278
+ return new (P || (P = Promise))(function(resolve2, reject) {
20279
20279
  function fulfilled(value) {
20280
20280
  try {
20281
20281
  step(generator.next(value));
@@ -20291,7 +20291,7 @@ function __awaiter2(thisArg, _arguments, P, generator) {
20291
20291
  }
20292
20292
  }
20293
20293
  function step(result) {
20294
- result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
20294
+ result.done ? resolve2(result.value) : adopt(result.value).then(fulfilled, rejected);
20295
20295
  }
20296
20296
  step((generator = generator.apply(thisArg, _arguments || [])).next());
20297
20297
  });
@@ -35513,8 +35513,8 @@ var SiteHistoryService = class _SiteHistoryService {
35513
35513
  const previousLock = _SiteHistoryService.sessionLocks.get(key) ?? Promise.resolve();
35514
35514
  let releaseCurrentLock = () => {
35515
35515
  };
35516
- const currentLock = new Promise((resolve) => {
35517
- releaseCurrentLock = resolve;
35516
+ const currentLock = new Promise((resolve2) => {
35517
+ releaseCurrentLock = resolve2;
35518
35518
  });
35519
35519
  const queuedLock = previousLock.catch(() => {
35520
35520
  }).then(() => currentLock);
@@ -37201,23 +37201,44 @@ function fail(message, code = 1) {
37201
37201
 
37202
37202
  // src/utils/config.ts
37203
37203
  import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
37204
- import { dirname } from "path";
37204
+ import { dirname, join as join2, resolve } from "path";
37205
+ import { homedir as homedir2 } from "os";
37205
37206
  var PROJECT_CONFIG = ".neopressrc.json";
37206
37207
  var WORKSPACE_CONFIG = ".neopress/config.json";
37207
- function readProjectConfig() {
37208
- let config2 = {};
37209
- for (const file2 of [PROJECT_CONFIG, WORKSPACE_CONFIG]) {
37210
- try {
37211
- const parsed = JSON.parse(readFileSync2(file2, "utf-8"));
37212
- config2 = {
37213
- ...config2,
37214
- ...typeof parsed.siteId === "number" ? { siteId: parsed.siteId } : {},
37215
- ...typeof parsed.baseUrl === "string" ? { baseUrl: parsed.baseUrl } : {}
37216
- };
37217
- } catch {
37208
+ function readConfigFileAt(path) {
37209
+ try {
37210
+ const parsed = JSON.parse(readFileSync2(path, "utf-8"));
37211
+ return {
37212
+ ...typeof parsed.siteId === "number" ? { siteId: parsed.siteId } : {},
37213
+ ...typeof parsed.baseUrl === "string" ? { baseUrl: parsed.baseUrl } : {}
37214
+ };
37215
+ } catch {
37216
+ return {};
37217
+ }
37218
+ }
37219
+ function locateProjectConfig(startDir = process.cwd()) {
37220
+ const home = resolve(homedir2());
37221
+ let dir = resolve(startDir);
37222
+ while (true) {
37223
+ let merged = {};
37224
+ let foundPath;
37225
+ for (const rel of [PROJECT_CONFIG, WORKSPACE_CONFIG]) {
37226
+ const p = join2(dir, rel);
37227
+ const cfg = readConfigFileAt(p);
37228
+ if (Object.keys(cfg).length > 0) {
37229
+ merged = { ...merged, ...cfg };
37230
+ if (!foundPath) foundPath = p;
37231
+ }
37218
37232
  }
37233
+ if (Object.keys(merged).length > 0) return { config: merged, path: foundPath };
37234
+ const parent = dirname(dir);
37235
+ if (dir === home || parent === dir) break;
37236
+ dir = parent;
37219
37237
  }
37220
- return config2;
37238
+ return { config: {} };
37239
+ }
37240
+ function readProjectConfig() {
37241
+ return locateProjectConfig().config;
37221
37242
  }
37222
37243
  function writeWorkspaceConfig(next) {
37223
37244
  mkdirSync2(dirname(WORKSPACE_CONFIG), { recursive: true });
@@ -37244,12 +37265,24 @@ function setActiveSiteId(siteId) {
37244
37265
  }
37245
37266
  }
37246
37267
  var siteOverride;
37247
- function getSiteTarget() {
37268
+ function resolveSiteTarget() {
37248
37269
  if (siteOverride) {
37249
37270
  const n = parseInt(siteOverride, 10);
37250
- return String(n) === siteOverride ? n : siteOverride;
37271
+ const value = String(n) === siteOverride ? n : siteOverride;
37272
+ return { value, source: "flag", detail: "--site" };
37251
37273
  }
37252
- return getSiteId();
37274
+ const envSiteId = process.env.NEOPRESS_SITE_ID;
37275
+ if (envSiteId) return { value: parseInt(envSiteId, 10), source: "env", detail: "NEOPRESS_SITE_ID" };
37276
+ const located = locateProjectConfig();
37277
+ if (typeof located.config.siteId === "number") {
37278
+ return { value: located.config.siteId, source: "project-config", detail: located.path };
37279
+ }
37280
+ const active = loadSession().activeSiteId;
37281
+ if (active) return { value: active, source: "global-active", detail: "sites use" };
37282
+ return { value: void 0, source: "none" };
37283
+ }
37284
+ function getSiteTarget() {
37285
+ return resolveSiteTarget().value;
37253
37286
  }
37254
37287
 
37255
37288
  // src/utils/client.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neopress/cli",
3
- "version": "4.1.0",
3
+ "version": "4.2.0",
4
4
  "description": "Neopress CLI — manage your Neopress site from the terminal",
5
5
  "type": "module",
6
6
  "keywords": [