@neopress/cli 4.10.0 → 4.11.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.
package/README.md CHANGED
@@ -66,16 +66,33 @@ neopress entries publish <entryId>
66
66
 
67
67
  # Configure a reusable conversion event and funnel
68
68
  neopress analytics events create --data '{"name":"Signup","eventType":"form","path":"*","formId":"3"}'
69
+ neopress analytics events create --data '{"name":"Outbound links","eventType":"outbound"}'
69
70
  neopress analytics events update <eventId> --data '{"name":"Completed signup"}'
70
71
  neopress analytics funnels create --data @funnel.json
71
72
 
72
73
  # Preview, then publish the whole site
73
74
  neopress publish preview
74
75
  neopress publish
76
+
77
+ # Operate the site control plane
78
+ neopress domains status
79
+ neopress search-console authorize
80
+ neopress team list
81
+ neopress history list
82
+ neopress analytics funnels results <funnelId>
83
+
84
+ # Use exact-target destructive commands
85
+ neopress publish unpublish-pages 12 18
86
+ neopress domains remove example.com
75
87
  ```
76
88
 
77
89
  Run `neopress <command> --help` for the flags and examples of any command.
78
90
 
91
+ The API enforces the same site role, work-access, and plan entitlements for CLI,
92
+ SDK, and MCP calls. External API access starts at Launch; saved funnel results
93
+ require Growth analytics, custom-domain connection requires the custom-domain
94
+ feature, team management is Owner/Admin, and billing is Owner-only.
95
+
79
96
  ## JSON / AI mode
80
97
 
81
98
  Output is human-readable in a terminal and **automatically switches to JSON when
package/dist/bin.cjs CHANGED
@@ -3686,6 +3686,12 @@ var FormsEndpoint = class {
3686
3686
  async deleteResponse(formId, responseId) {
3687
3687
  await this.client.delete(`${this.basePath}/${formId}/responses/${responseId}`);
3688
3688
  }
3689
+ async getResponse(formId, responseId) {
3690
+ return (await this.client.get(`${this.basePath}/${formId}/responses/${responseId}`)).data;
3691
+ }
3692
+ async markResponseRead(formId, responseId) {
3693
+ return (await this.client.patch(`${this.basePath}/${formId}/responses/${responseId}`, { read: true })).data;
3694
+ }
3689
3695
  };
3690
3696
  //#endregion
3691
3697
  //#region ../sdk/src/endpoints/assets.ts
@@ -3833,8 +3839,14 @@ var PublishEndpoint = class {
3833
3839
  async preview() {
3834
3840
  return (await this.client.get(`${this.client.siteBasePath}/publish`)).data;
3835
3841
  }
3836
- async site() {
3837
- return (await this.client.post(`${this.client.siteBasePath}/publish`)).data;
3842
+ async site(selection) {
3843
+ return (await this.client.post(`${this.client.siteBasePath}/publish`, selection ? { selection } : void 0)).data;
3844
+ }
3845
+ async unpublishPages(pageIds) {
3846
+ return (await this.client.patch(`${this.client.siteBasePath}/publish`, { pageIds })).data;
3847
+ }
3848
+ async undeploy() {
3849
+ return (await this.client.delete(`${this.client.siteBasePath}/publish`)).data;
3838
3850
  }
3839
3851
  };
3840
3852
  //#endregion
@@ -4002,6 +4014,14 @@ var AnalyticsFunnelsEndpoint = class {
4002
4014
  async delete(funnelId) {
4003
4015
  await this.client.delete(`${this.basePath}/${funnelId}`);
4004
4016
  }
4017
+ async results(funnelId, params) {
4018
+ const query = new URLSearchParams();
4019
+ if (params?.dateFrom) query.set("dateFrom", params.dateFrom);
4020
+ if (params?.dateTo) query.set("dateTo", params.dateTo);
4021
+ if (params?.timezone) query.set("timezone", params.timezone);
4022
+ const suffix = query.size > 0 ? `?${query.toString()}` : "";
4023
+ return (await this.client.get(`${this.basePath}/${funnelId}/results${suffix}`)).data;
4024
+ }
4005
4025
  };
4006
4026
  //#endregion
4007
4027
  //#region ../sdk/src/endpoints/templates.ts
@@ -4130,6 +4150,122 @@ var LogosEndpoint = class {
4130
4150
  }
4131
4151
  };
4132
4152
  //#endregion
4153
+ //#region ../sdk/src/endpoints/domains.ts
4154
+ var DomainsEndpoint = class {
4155
+ client;
4156
+ constructor(client) {
4157
+ this.client = client;
4158
+ }
4159
+ get basePath() {
4160
+ return `${this.client.siteBasePath}/domains`;
4161
+ }
4162
+ async status() {
4163
+ return (await this.client.get(this.basePath)).data;
4164
+ }
4165
+ async connect(domain) {
4166
+ return (await this.client.post(this.basePath, { domain })).data;
4167
+ }
4168
+ async refresh() {
4169
+ return (await this.client.patch(this.basePath, {})).data;
4170
+ }
4171
+ async remove(domain) {
4172
+ return (await this.client.delete(this.basePath, { domain })).data;
4173
+ }
4174
+ };
4175
+ //#endregion
4176
+ //#region ../sdk/src/endpoints/search-console.ts
4177
+ var SearchConsoleConnectionEndpoint = class {
4178
+ client;
4179
+ constructor(client) {
4180
+ this.client = client;
4181
+ }
4182
+ get basePath() {
4183
+ return `${this.client.siteBasePath}/search-console`;
4184
+ }
4185
+ async status() {
4186
+ return (await this.client.get(this.basePath)).data;
4187
+ }
4188
+ async authorize(locale) {
4189
+ return (await this.client.post(this.basePath, locale ? { locale } : {})).data;
4190
+ }
4191
+ async disconnect() {
4192
+ return (await this.client.delete(this.basePath)).data;
4193
+ }
4194
+ };
4195
+ //#endregion
4196
+ //#region ../sdk/src/endpoints/billing.ts
4197
+ var BillingEndpoint = class {
4198
+ client;
4199
+ constructor(client) {
4200
+ this.client = client;
4201
+ }
4202
+ get basePath() {
4203
+ return `${this.client.siteBasePath}/billing`;
4204
+ }
4205
+ async status() {
4206
+ return (await this.client.get(this.basePath)).data;
4207
+ }
4208
+ async checkout(plan) {
4209
+ return (await this.client.post(`${this.basePath}/checkout`, { plan })).data;
4210
+ }
4211
+ async portal() {
4212
+ return (await this.client.post(`${this.basePath}/portal`)).data;
4213
+ }
4214
+ async cancel() {
4215
+ return (await this.client.post(`${this.basePath}/subscription/cancel`)).data;
4216
+ }
4217
+ async resume() {
4218
+ return (await this.client.post(`${this.basePath}/subscription/resume`)).data;
4219
+ }
4220
+ };
4221
+ //#endregion
4222
+ //#region ../sdk/src/endpoints/team.ts
4223
+ var TeamEndpoint = class {
4224
+ client;
4225
+ constructor(client) {
4226
+ this.client = client;
4227
+ }
4228
+ get basePath() {
4229
+ return `${this.client.siteBasePath}/team`;
4230
+ }
4231
+ async list() {
4232
+ return (await this.client.get(this.basePath)).data;
4233
+ }
4234
+ async invite(input) {
4235
+ return (await this.client.post(this.basePath, input)).data;
4236
+ }
4237
+ async updateRole(profileId, role) {
4238
+ return (await this.client.patch(`${this.basePath}/${profileId}`, { role })).data;
4239
+ }
4240
+ async remove(profileId) {
4241
+ return (await this.client.delete(`${this.basePath}/${profileId}`)).data;
4242
+ }
4243
+ async transferOwnership(profileId) {
4244
+ return (await this.client.post(`${this.basePath}/ownership`, { profileId })).data;
4245
+ }
4246
+ };
4247
+ //#endregion
4248
+ //#region ../sdk/src/endpoints/history.ts
4249
+ var HistoryEndpoint = class {
4250
+ client;
4251
+ constructor(client) {
4252
+ this.client = client;
4253
+ }
4254
+ get basePath() {
4255
+ return `${this.client.siteBasePath}/history/snapshots`;
4256
+ }
4257
+ async list(limit) {
4258
+ const query = limit === void 0 ? "" : `?limit=${encodeURIComponent(String(limit))}`;
4259
+ return (await this.client.get(`${this.basePath}${query}`)).data;
4260
+ }
4261
+ async get(snapshotId) {
4262
+ return (await this.client.get(`${this.basePath}/${snapshotId}`)).data;
4263
+ }
4264
+ async restore(snapshotId) {
4265
+ return (await this.client.post(`${this.basePath}/${snapshotId}/restore`)).data;
4266
+ }
4267
+ };
4268
+ //#endregion
4133
4269
  //#region ../sdk/src/client.ts
4134
4270
  /**
4135
4271
  * @neopress/sdk — API Client
@@ -4154,6 +4290,11 @@ var NeopressClient = class {
4154
4290
  templates;
4155
4291
  headshots;
4156
4292
  logos;
4293
+ domains;
4294
+ searchConsole;
4295
+ billing;
4296
+ team;
4297
+ history;
4157
4298
  constructor(options) {
4158
4299
  this.baseUrl = (options.baseUrl || "https://app.neopress.ai").replace(/\/$/, "");
4159
4300
  this.accessToken = options.accessToken || "";
@@ -4172,6 +4313,11 @@ var NeopressClient = class {
4172
4313
  this.templates = new TemplatesEndpoint(this);
4173
4314
  this.headshots = new HeadshotsEndpoint(this);
4174
4315
  this.logos = new LogosEndpoint(this);
4316
+ this.domains = new DomainsEndpoint(this);
4317
+ this.searchConsole = new SearchConsoleConnectionEndpoint(this);
4318
+ this.billing = new BillingEndpoint(this);
4319
+ this.team = new TeamEndpoint(this);
4320
+ this.history = new HistoryEndpoint(this);
4175
4321
  }
4176
4322
  get siteBasePath() {
4177
4323
  return `/api/v1/sites/${this.siteId}`;
@@ -4221,8 +4367,8 @@ var NeopressClient = class {
4221
4367
  async patch(path, body) {
4222
4368
  return this.request("PATCH", path, body);
4223
4369
  }
4224
- async delete(path) {
4225
- return this.request("DELETE", path);
4370
+ async delete(path, body) {
4371
+ return this.request("DELETE", path, body);
4226
4372
  }
4227
4373
  };
4228
4374
  //#endregion
@@ -4685,6 +4831,16 @@ Returns submitted responses newest-first, paginated (--page/--limit, default pag
4685
4831
  limit: parseInt(options.limit, 10)
4686
4832
  }));
4687
4833
  });
4834
+ forms.command("response-get <formId> <responseId>").description("Get one form response").action(async (formId, responseId) => {
4835
+ output(await (await getClientAsync()).forms.getResponse(parseInt(formId, 10), parseInt(responseId, 10)));
4836
+ });
4837
+ forms.command("response-mark-read <formId> <responseId>").description("Mark one form response as read").action(async (formId, responseId) => {
4838
+ output(await (await getClientAsync()).forms.markResponseRead(parseInt(formId, 10), parseInt(responseId, 10)));
4839
+ });
4840
+ forms.command("response-delete <formId> <responseId>").description("Delete one form response").action(async (formId, responseId) => {
4841
+ await (await getClientAsync()).forms.deleteResponse(parseInt(formId, 10), parseInt(responseId, 10));
4842
+ ok(`Form response ${responseId} deleted`);
4843
+ });
4688
4844
  forms.command("delete <formId>").description("Delete a form").action(async (formId) => {
4689
4845
  await (await getClientAsync()).forms.delete(parseInt(formId, 10));
4690
4846
  ok(`Form ${formId} deleted`);
@@ -4750,15 +4906,24 @@ Examples:
4750
4906
  //#endregion
4751
4907
  //#region src/commands/publish.ts
4752
4908
  function registerPublishCommands(program) {
4753
- program.command("publish").description("Publish site or preview changes").addHelpText("after", `
4909
+ const publish = program.command("publish").description("Publish site or preview changes").option("--selection <json>", "Selective publish JSON or @file path").addHelpText("after", `
4754
4910
  Examples:
4755
4911
  $ neopress publish preview Show what would change
4756
- $ neopress publish Publish all pending changes live`).action(async () => {
4757
- output(await (await getClientAsync()).publish.site());
4912
+ $ neopress publish Publish all pending changes live`).action(async (options) => {
4913
+ const client = await getClientAsync();
4914
+ const selection = options.selection ? JSON.parse(String(options.selection).startsWith("@") ? (0, node_fs.readFileSync)(String(options.selection).slice(1), "utf8") : String(options.selection)) : void 0;
4915
+ output(await client.publish.site(selection));
4758
4916
  if (!isJsonMode()) ok("Site published");
4759
- }).command("preview").description("Preview pending publish changes").action(async () => {
4917
+ });
4918
+ publish.command("preview").description("Preview pending publish changes").action(async () => {
4760
4919
  output(await (await getClientAsync()).publish.preview());
4761
4920
  });
4921
+ publish.command("unpublish-pages <pageIds...>").description("Remove exact page IDs from production").action(async (pageIds) => {
4922
+ output(await (await getClientAsync()).publish.unpublishPages(pageIds.map(Number)));
4923
+ });
4924
+ publish.command("undeploy").description("Take the whole site offline").action(async () => {
4925
+ output(await (await getClientAsync()).publish.undeploy());
4926
+ });
4762
4927
  }
4763
4928
  //#endregion
4764
4929
  //#region src/commands/redirects.ts
@@ -4952,8 +5117,9 @@ Examples:
4952
5117
  Examples:
4953
5118
  $ neopress analytics events list
4954
5119
  $ neopress analytics events create --data '{"name":"Signup","eventType":"form","path":"*","formId":"3"}'
5120
+ $ neopress analytics events create --data '{"name":"Outbound links","eventType":"outbound"}'
4955
5121
  $ neopress analytics events update <eventId> --data '{"name":"New label"}'
4956
- Event updates may rename an event with {name} or change display settings with {display}; tracking identity is immutable after creation. Create inputs use camelCase fields such as eventType, eventName, formId, scrollDepth, and dwellSeconds. The API returns persisted snake_case fields.`);
5122
+ Event updates may rename an event with {name} or change display settings with {display}; tracking identity is immutable after creation. Create inputs use camelCase fields such as eventType, eventName, formId, scrollDepth, and dwellSeconds. Outbound events need only name and eventType and match already-collected external link clicks. Historical visibility events remain readable but cannot be created. The API returns persisted snake_case fields.`);
4957
5123
  events.command("list").description("List saved analytics event definitions").action(async () => {
4958
5124
  output(await (await getClientAsync()).analytics.events.list());
4959
5125
  });
@@ -4982,6 +5148,13 @@ Funnel input has name, ordered steps using eventId, and windowMode/windowHours.
4982
5148
  funnels.command("get <funnelId>").description("Get a saved analytics funnel").action(async (funnelId) => {
4983
5149
  output(await (await getClientAsync()).analytics.funnels.get(funnelId));
4984
5150
  });
5151
+ funnels.command("results <funnelId>").description("Get aggregate results for a saved funnel").option("--date-from <date>", "Start date in YYYY-MM-DD").option("--date-to <date>", "End date in YYYY-MM-DD").option("--timezone <timezone>", "IANA reporting timezone").action(async (funnelId, options) => {
5152
+ output(await (await getClientAsync()).analytics.funnels.results(funnelId, {
5153
+ dateFrom: options.dateFrom,
5154
+ dateTo: options.dateTo,
5155
+ timezone: options.timezone
5156
+ }));
5157
+ });
4985
5158
  funnels.command("create").description("Create a saved analytics funnel").requiredOption("--data <json>", "Funnel definition JSON or @file path").action(async (options) => {
4986
5159
  output(await (await getClientAsync()).analytics.funnels.create(parseDefinitionInput(options.data, "--data")));
4987
5160
  });
@@ -5385,6 +5558,102 @@ function registerGuideCommands(program) {
5385
5558
  });
5386
5559
  }
5387
5560
  //#endregion
5561
+ //#region src/commands/domains.ts
5562
+ function registerDomainCommands(program) {
5563
+ const domains = program.command("domains").description("Manage the site's custom domain");
5564
+ domains.command("status").description("Get custom-domain status").action(async () => {
5565
+ output(await (await getClientAsync()).domains.status());
5566
+ });
5567
+ domains.command("connect <domain>").description("Connect a custom domain").action(async (domain) => output(await (await getClientAsync()).domains.connect(domain)));
5568
+ domains.command("refresh").description("Refresh DNS verification status").action(async () => {
5569
+ output(await (await getClientAsync()).domains.refresh());
5570
+ });
5571
+ domains.command("remove <domain>").description("Remove the exact currently connected domain").addHelpText("after", `
5572
+ Examples:
5573
+ $ neopress domains status
5574
+ $ neopress domains remove example.com
5575
+ Pass the exact domain returned by status so a concurrent replacement cannot be removed.`).action(async (domain) => output(await (await getClientAsync()).domains.remove(domain)));
5576
+ }
5577
+ //#endregion
5578
+ //#region src/commands/search-console.ts
5579
+ function registerSearchConsoleCommands(program) {
5580
+ const searchConsole = program.command("search-console").description("Manage the site's Google Search Console connection");
5581
+ searchConsole.command("status").description("Get connection status").action(async () => {
5582
+ output(await (await getClientAsync()).searchConsole.status());
5583
+ });
5584
+ searchConsole.command("authorize").description("Create an OAuth authorization URL").option("--locale <locale>", "Dashboard locale for the OAuth return flow").action(async (options) => {
5585
+ output(await (await getClientAsync()).searchConsole.authorize(options.locale));
5586
+ });
5587
+ searchConsole.command("disconnect").description("Disconnect Search Console").action(async () => {
5588
+ output(await (await getClientAsync()).searchConsole.disconnect());
5589
+ });
5590
+ }
5591
+ //#endregion
5592
+ //#region src/commands/billing.ts
5593
+ function registerBillingCommands(program) {
5594
+ const billing = program.command("billing").description("Manage owner-only billing handoffs");
5595
+ billing.command("status").description("Get plan and subscription status").action(async () => {
5596
+ output(await (await getClientAsync()).billing.status());
5597
+ });
5598
+ billing.command("checkout <plan>").description("Create a checkout URL for launch or growth").action(async (plan) => {
5599
+ if (plan !== "launch" && plan !== "growth") fail("Plan must be launch or growth.");
5600
+ output(await (await getClientAsync()).billing.checkout(plan));
5601
+ });
5602
+ billing.command("portal").description("Create a customer-portal URL").action(async () => {
5603
+ output(await (await getClientAsync()).billing.portal());
5604
+ });
5605
+ billing.command("cancel").description("Cancel at the end of the billing period").action(async () => {
5606
+ output(await (await getClientAsync()).billing.cancel());
5607
+ });
5608
+ billing.command("resume").description("Remove scheduled cancellation").action(async () => {
5609
+ output(await (await getClientAsync()).billing.resume());
5610
+ });
5611
+ }
5612
+ //#endregion
5613
+ //#region src/commands/team.ts
5614
+ function role(value) {
5615
+ if (value !== "admin" && value !== "editor" && value !== "viewer") fail("Role must be admin, editor, or viewer.");
5616
+ return value;
5617
+ }
5618
+ function registerTeamCommands(program) {
5619
+ const team = program.command("team").description("Manage project members and invitations");
5620
+ team.command("list").description("List active members and pending invitations").action(async () => {
5621
+ output(await (await getClientAsync()).team.list());
5622
+ });
5623
+ team.command("invite <email>").description("Invite a member").requiredOption("--role <role>", "admin, editor, or viewer").option("--locale <locale>", "Invitation email locale").action(async (email, options) => {
5624
+ output(await (await getClientAsync()).team.invite({
5625
+ email,
5626
+ role: role(options.role),
5627
+ locale: options.locale
5628
+ }));
5629
+ });
5630
+ team.command("update-role <profileId>").description("Change a member's role preset").requiredOption("--role <role>", "admin, editor, or viewer").action(async (profileId, options) => {
5631
+ output(await (await getClientAsync()).team.updateRole(profileId, role(options.role)));
5632
+ });
5633
+ team.command("remove <profileId>").description("Remove a member").action(async (profileId) => output(await (await getClientAsync()).team.remove(profileId)));
5634
+ team.command("transfer-ownership <profileId>").description("Transfer ownership to an active member").action(async (profileId) => {
5635
+ output(await (await getClientAsync()).team.transferOwnership(profileId));
5636
+ });
5637
+ }
5638
+ //#endregion
5639
+ //#region src/commands/history.ts
5640
+ function registerHistoryCommands(program) {
5641
+ const history = program.command("history").description("Inspect and restore entity snapshots");
5642
+ history.command("list").description("List restorable snapshots").option("--limit <n>", "Maximum snapshots", "20").action(async (options) => {
5643
+ output(await (await getClientAsync()).history.list(Number(options.limit)));
5644
+ });
5645
+ history.command("get <snapshotId>").description("Get one snapshot").action(async (snapshotId) => {
5646
+ output(await (await getClientAsync()).history.get(Number(snapshotId)));
5647
+ });
5648
+ history.command("restore <snapshotId>").description("Restore an exact page, layout, collection, or form snapshot").addHelpText("after", `
5649
+ Examples:
5650
+ $ neopress history list
5651
+ $ neopress history restore 123
5652
+ Restore changes draft state; page visibility and form settings may affect live behavior immediately.`).action(async (snapshotId) => {
5653
+ output(await (await getClientAsync()).history.restore(Number(snapshotId)));
5654
+ });
5655
+ }
5656
+ //#endregion
5388
5657
  //#region src/bin.ts
5389
5658
  /**
5390
5659
  * @neopress/cli — Neopress CLI
@@ -5393,7 +5662,7 @@ function registerGuideCommands(program) {
5393
5662
  * Designed for use with Claude Code and other AI tools via --json mode.
5394
5663
  */
5395
5664
  const program = new Command();
5396
- program.name("neopress").description("Neopress CLI — manage your site from the terminal").version("4.10.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) => {
5665
+ program.name("neopress").description("Neopress CLI — manage your site from the terminal").version("4.11.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) => {
5397
5666
  const opts = thisCommand.optsWithGlobals();
5398
5667
  if (opts.site) setSiteOverride(String(opts.site));
5399
5668
  if (opts.json || !process.stdout.isTTY) setJsonMode(true);
@@ -5413,6 +5682,11 @@ registerAnalyticsCommands(program);
5413
5682
  registerTemplateCommands(program);
5414
5683
  registerHeadshotCommands(program);
5415
5684
  registerLogoCommands(program);
5685
+ registerDomainCommands(program);
5686
+ registerSearchConsoleCommands(program);
5687
+ registerBillingCommands(program);
5688
+ registerTeamCommands(program);
5689
+ registerHistoryCommands(program);
5416
5690
  registerGuideCommands(program);
5417
5691
  program.addHelpText("after", `
5418
5692
  Quickstart:
@@ -5432,11 +5706,12 @@ Env vars:
5432
5706
  NEOPRESS_BASE_URL API base URL (defaults to the hosted Neopress app)
5433
5707
  `);
5434
5708
  program.parseAsync(process.argv).catch((err) => {
5435
- if (err?.code) console.error(JSON.stringify({
5709
+ if (err?.code) if (isJsonMode()) console.error(JSON.stringify({
5436
5710
  ok: false,
5437
5711
  error: err.message,
5438
5712
  code: err.code
5439
5713
  }));
5714
+ else console.error(`Error [${err.code}]: ${err.message}`);
5440
5715
  else console.error(err.message || err);
5441
5716
  process.exit(1);
5442
5717
  });
package/dist/index.d.ts CHANGED
@@ -191,11 +191,13 @@ interface SiteLayout {
191
191
  draftTsx: string | null;
192
192
  draftGlobalCss: string | null;
193
193
  draftNotFoundTsx: string | null;
194
+ draftI18n: unknown;
194
195
  prodTsx: string | null;
195
196
  prodJs: string | null;
196
197
  prodGlobalCss: string | null;
197
198
  prodNotFoundTsx: string | null;
198
199
  prodNotFoundJs: string | null;
200
+ prodI18n: unknown;
199
201
  }
200
202
  interface Headshot {
201
203
  id: number;
@@ -282,7 +284,9 @@ interface SearchConsoleQueryResult {
282
284
  };
283
285
  error?: string;
284
286
  }
285
- type AnalyticsEventType = "custom" | "page" | "click" | "form" | "scroll" | "visibility" | "dwell";
287
+ type AnalyticsEventType = "custom" | "page" | "click" | "form" | "scroll" | "visibility" | "dwell" | "outbound";
288
+ /** `visibility` remains readable for historical definitions but cannot be created. */
289
+ type AnalyticsEventCreateType = Exclude<AnalyticsEventType, "visibility">;
286
290
  type FunnelFilterField = "event.path" | "event.url" | "event.referrer" | "event.referrer_source" | "event.property" | "session.referrer" | "session.referrer_source" | "session.traffic_category" | "session.utm_source" | "session.utm_medium" | "session.utm_campaign" | "session.utm_content" | "session.utm_term";
287
291
  type FunnelFilterOperator = "eq" | "neq" | "contains" | "not_contains" | "starts_with" | "ends_with" | "exists" | "not_exists" | "gt" | "gte" | "lt" | "lte";
288
292
  type AnalyticsFunnelFilterCondition = {
@@ -308,6 +312,7 @@ interface AnalyticsEventDefinition {
308
312
  name: string;
309
313
  chart_visible: boolean;
310
314
  is_pinned: boolean;
315
+ sort_order?: number | null;
311
316
  event_type: AnalyticsEventType;
312
317
  event_name: string;
313
318
  path: string;
@@ -323,7 +328,7 @@ interface AnalyticsEventDefinitionInput {
323
328
  /** Optional client UUID; reuse it with the same payload after an uncertain create response. */
324
329
  id?: string;
325
330
  name: string;
326
- eventType: AnalyticsEventType;
331
+ eventType: AnalyticsEventCreateType;
327
332
  eventName?: string;
328
333
  path?: string;
329
334
  selector?: string;
@@ -555,6 +560,11 @@ declare class FormsEndpoint {
555
560
  limit?: number;
556
561
  }): Promise<PaginatedResponse<FormResponse>>;
557
562
  deleteResponse(formId: number, responseId: number): Promise<void>;
563
+ getResponse(formId: number, responseId: number): Promise<FormResponse>;
564
+ markResponseRead(formId: number, responseId: number): Promise<{
565
+ id: number;
566
+ readAt: string;
567
+ }>;
558
568
  }
559
569
  //#endregion
560
570
  //#region ../sdk/src/endpoints/assets.d.ts
@@ -640,6 +650,8 @@ declare class SiteEndpoint {
640
650
  draftTsx?: string;
641
651
  draftNotFoundTsx?: string;
642
652
  draftGlobalCss?: string;
653
+ /** Replaces draft translations; null clears them, omission preserves them. */
654
+ draftI18n?: unknown;
643
655
  }): Promise<SiteLayout>;
644
656
  delete(): Promise<{
645
657
  siteId: number;
@@ -676,11 +688,19 @@ declare class RedirectsEndpoint {
676
688
  }
677
689
  //#endregion
678
690
  //#region ../sdk/src/endpoints/publish.d.ts
691
+ interface PublishSelection {
692
+ pageIds?: number[];
693
+ collectionIds?: number[];
694
+ formIds?: number[];
695
+ includeLayout?: boolean;
696
+ }
679
697
  declare class PublishEndpoint {
680
698
  private readonly client;
681
699
  constructor(client: NeopressClient);
682
700
  preview(): Promise<unknown>;
683
- site(): Promise<unknown>;
701
+ site(selection?: PublishSelection): Promise<unknown>;
702
+ unpublishPages(pageIds: number[]): Promise<unknown>;
703
+ undeploy(): Promise<unknown>;
684
704
  }
685
705
  //#endregion
686
706
  //#region ../sdk/src/endpoints/entry-references.d.ts
@@ -743,6 +763,7 @@ declare class AnalyticsFunnelsEndpoint {
743
763
  create(data: AnalyticsFunnelDefinitionInput): Promise<AnalyticsFunnelDefinition>;
744
764
  update(funnelId: string, data: AnalyticsFunnelDefinitionInput): Promise<AnalyticsFunnelDefinition>;
745
765
  delete(funnelId: string): Promise<void>;
766
+ results(funnelId: string, params?: Pick<AnalyticsDateRangeParams, "dateFrom" | "dateTo" | "timezone">): Promise<AnalyticsQueryResult>;
746
767
  }
747
768
  //#endregion
748
769
  //#region ../sdk/src/endpoints/templates.d.ts
@@ -927,6 +948,139 @@ declare class LogosEndpoint {
927
948
  delete(id: number): Promise<LogoDeleteResult>;
928
949
  }
929
950
  //#endregion
951
+ //#region ../sdk/src/endpoints/domains.d.ts
952
+ interface DomainStatus {
953
+ domain: string | null;
954
+ domainType: string | null;
955
+ verified: boolean | null;
956
+ }
957
+ declare class DomainsEndpoint {
958
+ private readonly client;
959
+ constructor(client: NeopressClient);
960
+ private get basePath();
961
+ status(): Promise<DomainStatus>;
962
+ connect(domain: string): Promise<DomainStatus>;
963
+ refresh(): Promise<DomainStatus & Record<string, unknown>>;
964
+ remove(domain: string): Promise<{
965
+ removedDomain: string;
966
+ removedFromProvider: boolean;
967
+ providerError: string | null;
968
+ }>;
969
+ }
970
+ //#endregion
971
+ //#region ../sdk/src/endpoints/search-console.d.ts
972
+ interface SearchConsoleConnectionStatus {
973
+ authorized: boolean;
974
+ connected: boolean;
975
+ propertyUrl: string | null;
976
+ status: string | null;
977
+ disconnectReason: string | null;
978
+ provisioning: unknown;
979
+ }
980
+ declare class SearchConsoleConnectionEndpoint {
981
+ private readonly client;
982
+ constructor(client: NeopressClient);
983
+ private get basePath();
984
+ status(): Promise<SearchConsoleConnectionStatus>;
985
+ authorize(locale?: string): Promise<{
986
+ authorizationUrl: string;
987
+ requiresUserAction: true;
988
+ }>;
989
+ disconnect(): Promise<{
990
+ disconnected: true;
991
+ }>;
992
+ }
993
+ //#endregion
994
+ //#region ../sdk/src/endpoints/billing.d.ts
995
+ interface BillingStatus {
996
+ planKey: string | null;
997
+ customTrialEndsAt: string | null;
998
+ prepaidGrowthEndsAt: string | null;
999
+ subscription: {
1000
+ status: string | null;
1001
+ cancelAtPeriodEnd: boolean | null;
1002
+ currentPeriodStart: string | null;
1003
+ currentPeriodEnd: string | null;
1004
+ } | null;
1005
+ }
1006
+ declare class BillingEndpoint {
1007
+ private readonly client;
1008
+ constructor(client: NeopressClient);
1009
+ private get basePath();
1010
+ status(): Promise<BillingStatus>;
1011
+ checkout(plan: "launch" | "growth"): Promise<{
1012
+ checkoutUrl: string;
1013
+ requiresUserAction: true;
1014
+ }>;
1015
+ portal(): Promise<{
1016
+ portalUrl: string;
1017
+ requiresUserAction: true;
1018
+ }>;
1019
+ cancel(): Promise<{
1020
+ cancelAtPeriodEnd: boolean;
1021
+ effectiveAt: string | null;
1022
+ }>;
1023
+ resume(): Promise<{
1024
+ cancelAtPeriodEnd: boolean;
1025
+ effectiveAt: string | null;
1026
+ }>;
1027
+ }
1028
+ //#endregion
1029
+ //#region ../sdk/src/endpoints/team.d.ts
1030
+ type TeamRole = "admin" | "editor" | "viewer";
1031
+ interface TeamListResult {
1032
+ members: unknown[];
1033
+ invitations: unknown[];
1034
+ }
1035
+ declare class TeamEndpoint {
1036
+ private readonly client;
1037
+ constructor(client: NeopressClient);
1038
+ private get basePath();
1039
+ list(): Promise<TeamListResult>;
1040
+ invite(input: {
1041
+ email: string;
1042
+ role: TeamRole;
1043
+ locale?: string;
1044
+ }): Promise<unknown>;
1045
+ updateRole(profileId: string, role: TeamRole): Promise<{
1046
+ updated: true;
1047
+ }>;
1048
+ remove(profileId: string): Promise<{
1049
+ removed: true;
1050
+ }>;
1051
+ transferOwnership(profileId: string): Promise<{
1052
+ transferred: true;
1053
+ alreadyTransferred?: true;
1054
+ }>;
1055
+ }
1056
+ //#endregion
1057
+ //#region ../sdk/src/endpoints/history.d.ts
1058
+ interface EntitySnapshotSummary {
1059
+ id: number;
1060
+ entityType: "page" | "site_layout" | "collection" | "form";
1061
+ entityId: number;
1062
+ createdAt: string;
1063
+ }
1064
+ interface EntitySnapshot extends EntitySnapshotSummary {
1065
+ data: unknown;
1066
+ }
1067
+ declare class HistoryEndpoint {
1068
+ private readonly client;
1069
+ constructor(client: NeopressClient);
1070
+ private get basePath();
1071
+ list(limit?: number): Promise<{
1072
+ snapshots: EntitySnapshotSummary[];
1073
+ hasMore: boolean;
1074
+ }>;
1075
+ get(snapshotId: number): Promise<EntitySnapshot>;
1076
+ restore(snapshotId: number): Promise<{
1077
+ restored: true;
1078
+ snapshotId: number;
1079
+ entityType: string;
1080
+ entityId: number;
1081
+ }>;
1082
+ }
1083
+ //#endregion
930
1084
  //#region ../sdk/src/client.d.ts
931
1085
  /**
932
1086
  * ⚠️ No `supabaseUrl` / `supabaseAnonKey`. This client speaks HTTP to
@@ -964,6 +1118,11 @@ declare class NeopressClient {
964
1118
  readonly templates: TemplatesEndpoint;
965
1119
  readonly headshots: HeadshotsEndpoint;
966
1120
  readonly logos: LogosEndpoint;
1121
+ readonly domains: DomainsEndpoint;
1122
+ readonly searchConsole: SearchConsoleConnectionEndpoint;
1123
+ readonly billing: BillingEndpoint;
1124
+ readonly team: TeamEndpoint;
1125
+ readonly history: HistoryEndpoint;
967
1126
  constructor(options: NeopressClientOptions);
968
1127
  get siteBasePath(): string;
969
1128
  request<T>(method: string, path: string, body?: unknown): Promise<T>;
@@ -971,7 +1130,7 @@ declare class NeopressClient {
971
1130
  getList<T>(path: string): Promise<PaginatedResponse<T>>;
972
1131
  post<T>(path: string, body?: unknown): Promise<ApiResponse<T>>;
973
1132
  patch<T>(path: string, body: unknown): Promise<ApiResponse<T>>;
974
- delete<T>(path: string): Promise<ApiResponse<T>>;
1133
+ delete<T>(path: string, body?: unknown): Promise<ApiResponse<T>>;
975
1134
  }
976
1135
  //#endregion
977
1136
  //#region src/utils/client.d.ts
package/dist/index.js CHANGED
@@ -245,6 +245,12 @@ var FormsEndpoint = class {
245
245
  async deleteResponse(formId, responseId) {
246
246
  await this.client.delete(`${this.basePath}/${formId}/responses/${responseId}`);
247
247
  }
248
+ async getResponse(formId, responseId) {
249
+ return (await this.client.get(`${this.basePath}/${formId}/responses/${responseId}`)).data;
250
+ }
251
+ async markResponseRead(formId, responseId) {
252
+ return (await this.client.patch(`${this.basePath}/${formId}/responses/${responseId}`, { read: true })).data;
253
+ }
248
254
  };
249
255
  //#endregion
250
256
  //#region ../sdk/src/endpoints/assets.ts
@@ -392,8 +398,14 @@ var PublishEndpoint = class {
392
398
  async preview() {
393
399
  return (await this.client.get(`${this.client.siteBasePath}/publish`)).data;
394
400
  }
395
- async site() {
396
- return (await this.client.post(`${this.client.siteBasePath}/publish`)).data;
401
+ async site(selection) {
402
+ return (await this.client.post(`${this.client.siteBasePath}/publish`, selection ? { selection } : void 0)).data;
403
+ }
404
+ async unpublishPages(pageIds) {
405
+ return (await this.client.patch(`${this.client.siteBasePath}/publish`, { pageIds })).data;
406
+ }
407
+ async undeploy() {
408
+ return (await this.client.delete(`${this.client.siteBasePath}/publish`)).data;
397
409
  }
398
410
  };
399
411
  //#endregion
@@ -561,6 +573,14 @@ var AnalyticsFunnelsEndpoint = class {
561
573
  async delete(funnelId) {
562
574
  await this.client.delete(`${this.basePath}/${funnelId}`);
563
575
  }
576
+ async results(funnelId, params) {
577
+ const query = new URLSearchParams();
578
+ if (params?.dateFrom) query.set("dateFrom", params.dateFrom);
579
+ if (params?.dateTo) query.set("dateTo", params.dateTo);
580
+ if (params?.timezone) query.set("timezone", params.timezone);
581
+ const suffix = query.size > 0 ? `?${query.toString()}` : "";
582
+ return (await this.client.get(`${this.basePath}/${funnelId}/results${suffix}`)).data;
583
+ }
564
584
  };
565
585
  //#endregion
566
586
  //#region ../sdk/src/endpoints/templates.ts
@@ -689,6 +709,122 @@ var LogosEndpoint = class {
689
709
  }
690
710
  };
691
711
  //#endregion
712
+ //#region ../sdk/src/endpoints/domains.ts
713
+ var DomainsEndpoint = class {
714
+ client;
715
+ constructor(client) {
716
+ this.client = client;
717
+ }
718
+ get basePath() {
719
+ return `${this.client.siteBasePath}/domains`;
720
+ }
721
+ async status() {
722
+ return (await this.client.get(this.basePath)).data;
723
+ }
724
+ async connect(domain) {
725
+ return (await this.client.post(this.basePath, { domain })).data;
726
+ }
727
+ async refresh() {
728
+ return (await this.client.patch(this.basePath, {})).data;
729
+ }
730
+ async remove(domain) {
731
+ return (await this.client.delete(this.basePath, { domain })).data;
732
+ }
733
+ };
734
+ //#endregion
735
+ //#region ../sdk/src/endpoints/search-console.ts
736
+ var SearchConsoleConnectionEndpoint = class {
737
+ client;
738
+ constructor(client) {
739
+ this.client = client;
740
+ }
741
+ get basePath() {
742
+ return `${this.client.siteBasePath}/search-console`;
743
+ }
744
+ async status() {
745
+ return (await this.client.get(this.basePath)).data;
746
+ }
747
+ async authorize(locale) {
748
+ return (await this.client.post(this.basePath, locale ? { locale } : {})).data;
749
+ }
750
+ async disconnect() {
751
+ return (await this.client.delete(this.basePath)).data;
752
+ }
753
+ };
754
+ //#endregion
755
+ //#region ../sdk/src/endpoints/billing.ts
756
+ var BillingEndpoint = class {
757
+ client;
758
+ constructor(client) {
759
+ this.client = client;
760
+ }
761
+ get basePath() {
762
+ return `${this.client.siteBasePath}/billing`;
763
+ }
764
+ async status() {
765
+ return (await this.client.get(this.basePath)).data;
766
+ }
767
+ async checkout(plan) {
768
+ return (await this.client.post(`${this.basePath}/checkout`, { plan })).data;
769
+ }
770
+ async portal() {
771
+ return (await this.client.post(`${this.basePath}/portal`)).data;
772
+ }
773
+ async cancel() {
774
+ return (await this.client.post(`${this.basePath}/subscription/cancel`)).data;
775
+ }
776
+ async resume() {
777
+ return (await this.client.post(`${this.basePath}/subscription/resume`)).data;
778
+ }
779
+ };
780
+ //#endregion
781
+ //#region ../sdk/src/endpoints/team.ts
782
+ var TeamEndpoint = class {
783
+ client;
784
+ constructor(client) {
785
+ this.client = client;
786
+ }
787
+ get basePath() {
788
+ return `${this.client.siteBasePath}/team`;
789
+ }
790
+ async list() {
791
+ return (await this.client.get(this.basePath)).data;
792
+ }
793
+ async invite(input) {
794
+ return (await this.client.post(this.basePath, input)).data;
795
+ }
796
+ async updateRole(profileId, role) {
797
+ return (await this.client.patch(`${this.basePath}/${profileId}`, { role })).data;
798
+ }
799
+ async remove(profileId) {
800
+ return (await this.client.delete(`${this.basePath}/${profileId}`)).data;
801
+ }
802
+ async transferOwnership(profileId) {
803
+ return (await this.client.post(`${this.basePath}/ownership`, { profileId })).data;
804
+ }
805
+ };
806
+ //#endregion
807
+ //#region ../sdk/src/endpoints/history.ts
808
+ var HistoryEndpoint = class {
809
+ client;
810
+ constructor(client) {
811
+ this.client = client;
812
+ }
813
+ get basePath() {
814
+ return `${this.client.siteBasePath}/history/snapshots`;
815
+ }
816
+ async list(limit) {
817
+ const query = limit === void 0 ? "" : `?limit=${encodeURIComponent(String(limit))}`;
818
+ return (await this.client.get(`${this.basePath}${query}`)).data;
819
+ }
820
+ async get(snapshotId) {
821
+ return (await this.client.get(`${this.basePath}/${snapshotId}`)).data;
822
+ }
823
+ async restore(snapshotId) {
824
+ return (await this.client.post(`${this.basePath}/${snapshotId}/restore`)).data;
825
+ }
826
+ };
827
+ //#endregion
692
828
  //#region ../sdk/src/client.ts
693
829
  /**
694
830
  * @neopress/sdk — API Client
@@ -713,6 +849,11 @@ var NeopressClient = class {
713
849
  templates;
714
850
  headshots;
715
851
  logos;
852
+ domains;
853
+ searchConsole;
854
+ billing;
855
+ team;
856
+ history;
716
857
  constructor(options) {
717
858
  this.baseUrl = (options.baseUrl || "https://app.neopress.ai").replace(/\/$/, "");
718
859
  this.accessToken = options.accessToken || "";
@@ -731,6 +872,11 @@ var NeopressClient = class {
731
872
  this.templates = new TemplatesEndpoint(this);
732
873
  this.headshots = new HeadshotsEndpoint(this);
733
874
  this.logos = new LogosEndpoint(this);
875
+ this.domains = new DomainsEndpoint(this);
876
+ this.searchConsole = new SearchConsoleConnectionEndpoint(this);
877
+ this.billing = new BillingEndpoint(this);
878
+ this.team = new TeamEndpoint(this);
879
+ this.history = new HistoryEndpoint(this);
734
880
  }
735
881
  get siteBasePath() {
736
882
  return `/api/v1/sites/${this.siteId}`;
@@ -780,8 +926,8 @@ var NeopressClient = class {
780
926
  async patch(path, body) {
781
927
  return this.request("PATCH", path, body);
782
928
  }
783
- async delete(path) {
784
- return this.request("DELETE", path);
929
+ async delete(path, body) {
930
+ return this.request("DELETE", path, body);
785
931
  }
786
932
  };
787
933
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neopress/cli",
3
- "version": "4.10.0",
3
+ "version": "4.11.0",
4
4
  "description": "Neopress CLI — manage your Neopress site from the terminal",
5
5
  "type": "module",
6
6
  "keywords": [