@zeroxyz/cli 1.31.0 → 1.32.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 (2) hide show
  1. package/dist/index.js +282 -10
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -93043,7 +93043,7 @@ init_esm_shims();
93043
93043
  // ../sdk/dist/index.js
93044
93044
  init_esm_shims();
93045
93045
 
93046
- // ../sdk/dist/chunk-QHTPKBCA.js
93046
+ // ../sdk/dist/chunk-4H5K6DCA.js
93047
93047
  init_esm_shims();
93048
93048
 
93049
93049
  // ../../node_modules/.pnpm/viem@2.52.2_bufferutil@4.1.0_typescript@5.9.3_utf-8-validate@6.0.6_zod@4.3.6/node_modules/viem/_esm/index.js
@@ -166839,7 +166839,7 @@ var redactUrl = (raw) => {
166839
166839
  };
166840
166840
  var truncateError = (raw) => raw.length > ERROR_MAX ? `${raw.slice(0, ERROR_MAX)}\u2026` : raw;
166841
166841
  var package_default = {
166842
- version: "0.24.0"
166842
+ version: "0.25.0"
166843
166843
  };
166844
166844
  var SDK_VERSION2 = package_default.version;
166845
166845
  var ZeroError = class extends Error {
@@ -167352,12 +167352,12 @@ var request2 = async (client, opts, schema) => {
167352
167352
  }
167353
167353
  continue;
167354
167354
  }
167355
- const errorBody = await parseErrorBody(response);
167355
+ const errorBody2 = await parseErrorBody(response);
167356
167356
  const requestId = response.headers.get("x-request-id") ?? void 0;
167357
- throw new ZeroApiError(errorMessageFromBody(errorBody, response.status), {
167357
+ throw new ZeroApiError(errorMessageFromBody(errorBody2, response.status), {
167358
167358
  status: response.status,
167359
167359
  requestId,
167360
- body: errorBody
167360
+ body: errorBody2
167361
167361
  });
167362
167362
  }
167363
167363
  throw new ZeroApiError("Exhausted retries", {
@@ -169743,6 +169743,12 @@ var withDefaultContentType = (headers, body) => {
169743
169743
  }
169744
169744
  return next;
169745
169745
  };
169746
+ var withDefaultUserAgent = (headers) => {
169747
+ const next = headers ? { ...headers } : {};
169748
+ const hasUa = Object.keys(next).some((k) => k.toLowerCase() === "user-agent");
169749
+ if (!hasUa) next["user-agent"] = `zero-sdk/${SDK_VERSION2}`;
169750
+ return next;
169751
+ };
169746
169752
  var clientFetch = async (client, url4, opts = {}, diagnostics) => {
169747
169753
  const startedAt = Date.now();
169748
169754
  const fetchId = diagnostics.fetchId;
@@ -169770,7 +169776,9 @@ var clientFetch = async (client, url4, opts = {}, diagnostics) => {
169770
169776
  );
169771
169777
  return null;
169772
169778
  }) : Promise.resolve(null);
169773
- const probeHeaders = withDefaultContentType(opts.headers, requestBody);
169779
+ const probeHeaders = withDefaultUserAgent(
169780
+ withDefaultContentType(opts.headers, requestBody)
169781
+ );
169774
169782
  const requestInit = {
169775
169783
  method,
169776
169784
  headers: probeHeaders,
@@ -169850,7 +169858,9 @@ var clientFetch = async (client, url4, opts = {}, diagnostics) => {
169850
169858
  // Fresh clone for the paid retry — same rationale as
169851
169859
  // the probe-side clone above. Re-derives the default
169852
169860
  // Content-Type so the paid leg matches the probe.
169853
- headers: withDefaultContentType(opts.headers, requestBody),
169861
+ headers: withDefaultUserAgent(
169862
+ withDefaultContentType(opts.headers, requestBody)
169863
+ ),
169854
169864
  body: requestBody,
169855
169865
  maxPay: opts.maxPay,
169856
169866
  account: opts.account,
@@ -170280,6 +170290,214 @@ var clientFetch = async (client, url4, opts = {}, diagnostics) => {
170280
170290
  result.capabilityResolution = capabilityResolution;
170281
170291
  return result;
170282
170292
  };
170293
+ var usdAmountSchema = external_exports3.string().regex(/^\d+(?:\.\d{1,6})?$/, "Expected a decimal USD amount");
170294
+ var creditPurchaseSchema = external_exports3.object({
170295
+ url: external_exports3.string().url(),
170296
+ amountRequired: external_exports3.literal(true),
170297
+ minimumUsd: usdAmountSchema
170298
+ });
170299
+ var storefrontPlanSchema = external_exports3.object({
170300
+ id: external_exports3.string().min(1),
170301
+ name: external_exports3.string().min(1),
170302
+ slug: external_exports3.string().min(1),
170303
+ billingMode: external_exports3.string().min(1),
170304
+ purchase: creditPurchaseSchema.nullable()
170305
+ });
170306
+ var storefrontManifestSchema = external_exports3.object({
170307
+ seller: external_exports3.object({
170308
+ id: external_exports3.string().min(1),
170309
+ name: external_exports3.string().min(1),
170310
+ slug: external_exports3.string().min(1)
170311
+ }),
170312
+ plans: external_exports3.array(storefrontPlanSchema)
170313
+ });
170314
+ var USD_MICROS = 1000000n;
170315
+ var CENT_MICROS = 10000n;
170316
+ var parseUsdMicros = (amount2) => {
170317
+ if (!/^\d+(?:\.\d{1,6})?$/.test(amount2)) {
170318
+ throw new ZeroValidationError(
170319
+ "Credit purchase amount must be a positive decimal with at most 6 fractional digits."
170320
+ );
170321
+ }
170322
+ const [whole = "0", fraction = ""] = amount2.split(".");
170323
+ return BigInt(whole) * USD_MICROS + BigInt(fraction.padEnd(6, "0"));
170324
+ };
170325
+ var formatUsdMicros = (amount2) => {
170326
+ const whole = amount2 / USD_MICROS;
170327
+ const fraction = (amount2 % USD_MICROS).toString().padStart(6, "0");
170328
+ return `${whole}.${fraction}`;
170329
+ };
170330
+ var resourceOrigin = (resourceUrl) => {
170331
+ let parsed;
170332
+ try {
170333
+ parsed = new URL(resourceUrl);
170334
+ } catch (cause) {
170335
+ throw new ZeroValidationError(
170336
+ "Credit access requires a valid resource URL.",
170337
+ {
170338
+ cause
170339
+ }
170340
+ );
170341
+ }
170342
+ if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
170343
+ throw new ZeroValidationError(
170344
+ "Credit access only supports HTTP or HTTPS resources."
170345
+ );
170346
+ }
170347
+ return parsed.origin;
170348
+ };
170349
+ var errorBody = async (response) => {
170350
+ const text = await response.text().catch(() => "");
170351
+ try {
170352
+ return JSON.parse(text);
170353
+ } catch {
170354
+ return text || null;
170355
+ }
170356
+ };
170357
+ var Access = class {
170358
+ constructor(client) {
170359
+ this.client = client;
170360
+ }
170361
+ discoverCreditPlans = async (resourceUrl, opts = {}) => {
170362
+ const origin2 = resourceOrigin(resourceUrl);
170363
+ const manifestUrl = new URL("/manifest.json", origin2).href;
170364
+ let response;
170365
+ try {
170366
+ response = await this.client.fetchImpl(manifestUrl, {
170367
+ headers: { accept: "application/json" },
170368
+ signal: opts.signal
170369
+ });
170370
+ } catch (cause) {
170371
+ throw new ZeroApiError("Seller manifest request failed", {
170372
+ status: 0,
170373
+ cause
170374
+ });
170375
+ }
170376
+ if (!response.ok) {
170377
+ throw new ZeroApiError("Seller manifest request failed", {
170378
+ status: response.status,
170379
+ body: await errorBody(response)
170380
+ });
170381
+ }
170382
+ const text = await response.text();
170383
+ let json3;
170384
+ try {
170385
+ json3 = JSON.parse(text);
170386
+ } catch (cause) {
170387
+ throw new ZeroValidationError(
170388
+ "Seller manifest did not contain valid JSON.",
170389
+ { cause, body: text }
170390
+ );
170391
+ }
170392
+ const parsed = storefrontManifestSchema.safeParse(json3);
170393
+ if (!parsed.success) {
170394
+ throw new ZeroValidationError(
170395
+ "Seller manifest did not match the expected access schema.",
170396
+ { cause: parsed.error, body: text }
170397
+ );
170398
+ }
170399
+ const creditPlans = [];
170400
+ for (const plan of parsed.data.plans) {
170401
+ if (plan.billingMode !== "credit" || !plan.purchase) continue;
170402
+ const purchaseUrl = new URL(plan.purchase.url);
170403
+ if (purchaseUrl.origin !== origin2) {
170404
+ throw new ZeroValidationError(
170405
+ "Seller manifest advertised a cross-origin credit purchase URL."
170406
+ );
170407
+ }
170408
+ creditPlans.push({
170409
+ id: plan.id,
170410
+ name: plan.name,
170411
+ slug: plan.slug,
170412
+ minimumUsd: formatUsdMicros(parseUsdMicros(plan.purchase.minimumUsd))
170413
+ });
170414
+ }
170415
+ return {
170416
+ resourceOrigin: origin2,
170417
+ seller: parsed.data.seller,
170418
+ onlyCreditPlans: parsed.data.plans.length > 0 && parsed.data.plans.every((plan) => plan.billingMode === "credit"),
170419
+ plans: creditPlans
170420
+ };
170421
+ };
170422
+ prepareCreditPurchase = async (input) => {
170423
+ const discovery = await this.discoverCreditPlans(input.resourceUrl, {
170424
+ signal: input.signal
170425
+ });
170426
+ const plan = discovery.plans.find(
170427
+ (candidate) => candidate.id === input.planId
170428
+ );
170429
+ if (!plan) {
170430
+ throw new ZeroValidationError(
170431
+ "The requested credit plan is not purchasable in the seller's current manifest."
170432
+ );
170433
+ }
170434
+ const amount2 = parseUsdMicros(input.amountUsd);
170435
+ const minimum = parseUsdMicros(plan.minimumUsd);
170436
+ if (amount2 <= 0n || amount2 < minimum) {
170437
+ throw new ZeroValidationError(
170438
+ `Credit purchase amount must be at least $${plan.minimumUsd}.`
170439
+ );
170440
+ }
170441
+ if (amount2 % CENT_MICROS !== 0n) {
170442
+ throw new ZeroValidationError(
170443
+ "Credit purchase amount must be in whole-cent increments."
170444
+ );
170445
+ }
170446
+ const manifest = storefrontManifestSchema.parse(
170447
+ await this.fetchManifest(discovery.resourceOrigin, input.signal)
170448
+ );
170449
+ const current = manifest.plans.find(
170450
+ (candidate) => candidate.id === input.planId && candidate.billingMode === "credit"
170451
+ );
170452
+ if (!current?.purchase) {
170453
+ throw new ZeroValidationError(
170454
+ "The requested credit plan is no longer purchasable."
170455
+ );
170456
+ }
170457
+ const currentMinimum = parseUsdMicros(current.purchase.minimumUsd);
170458
+ if (amount2 < currentMinimum) {
170459
+ throw new ZeroValidationError(
170460
+ `Credit purchase amount must be at least $${formatUsdMicros(currentMinimum)}.`
170461
+ );
170462
+ }
170463
+ const purchaseUrl = new URL(current.purchase.url);
170464
+ if (purchaseUrl.origin !== discovery.resourceOrigin) {
170465
+ throw new ZeroValidationError(
170466
+ "Seller manifest advertised a cross-origin credit purchase URL."
170467
+ );
170468
+ }
170469
+ const amountUsd = formatUsdMicros(amount2);
170470
+ return {
170471
+ resourceOrigin: discovery.resourceOrigin,
170472
+ plan: {
170473
+ id: current.id,
170474
+ name: current.name,
170475
+ slug: current.slug,
170476
+ minimumUsd: formatUsdMicros(currentMinimum)
170477
+ },
170478
+ url: purchaseUrl.href,
170479
+ method: "POST",
170480
+ body: JSON.stringify({ amountUsd }),
170481
+ amountUsd
170482
+ };
170483
+ };
170484
+ fetchManifest = async (origin2, signal) => {
170485
+ const response = await this.client.fetchImpl(
170486
+ new URL("/manifest.json", origin2),
170487
+ {
170488
+ headers: { accept: "application/json" },
170489
+ signal
170490
+ }
170491
+ );
170492
+ if (!response.ok) {
170493
+ throw new ZeroApiError("Seller manifest request failed", {
170494
+ status: response.status,
170495
+ body: await errorBody(response)
170496
+ });
170497
+ }
170498
+ return response.json();
170499
+ };
170500
+ };
170283
170501
  var agentAuthMetadataSchema = external_exports3.object({
170284
170502
  token_endpoint: external_exports3.string().optional(),
170285
170503
  agent_auth: external_exports3.object({
@@ -172322,6 +172540,7 @@ var ZeroClient = class _ZeroClient {
172322
172540
  // is called. Lazy getters would tree-shake better but break the discoverable
172323
172541
  // `client.<tab>` ergonomics that make resource-namespaced SDKs pleasant.
172324
172542
  auth;
172543
+ access;
172325
172544
  bugReports;
172326
172545
  capabilities;
172327
172546
  payments;
@@ -172344,6 +172563,7 @@ var ZeroClient = class _ZeroClient {
172344
172563
  this.analyticsOptions = options.analytics;
172345
172564
  this.refreshOverride = options.refresh;
172346
172565
  this.withAccountCache = options._sharedAccountCache ?? /* @__PURE__ */ new Map();
172566
+ this.access = new Access(this);
172347
172567
  this.auth = new Auth(this);
172348
172568
  this.bugReports = new BugReports(this);
172349
172569
  this.capabilities = new Capabilities(this);
@@ -176416,7 +176636,51 @@ var placeholderFor = (fieldName, propSchema) => String(sampleValueFor(fieldName,
176416
176636
 
176417
176637
  // package.json
176418
176638
  var package_default2 = {
176419
- version: "1.31.0"};
176639
+ name: "@zeroxyz/cli",
176640
+ version: "1.32.0",
176641
+ type: "module",
176642
+ bin: {
176643
+ zero: "dist/index.js",
176644
+ zerocli: "dist/index.js"
176645
+ },
176646
+ files: [
176647
+ "dist"
176648
+ ],
176649
+ publishConfig: {
176650
+ access: "public"
176651
+ },
176652
+ scripts: {
176653
+ build: "tsup",
176654
+ "build:binary": "tsup --config tsup.binary.ts && pnpm exec pkg dist/pkg/index.cjs --config pkg.json --targets node24-macos-arm64,node24-macos-x64,node24-linux-x64,node24-linux-arm64,node24-win-x64 --output dist/bin/zero",
176655
+ prepublishOnly: "pnpm run build",
176656
+ dev: "ZERO_ENV=development tsx src/index.ts",
176657
+ cli: "ZERO_ENV=development ZERO_API_URL=http://localhost:1111 tsx src/index.ts",
176658
+ "test:integration": "vitest run --project integration",
176659
+ "test:e2e": "tsup && vitest run --project e2e",
176660
+ "test:online": "vitest run --project online",
176661
+ "test:unit": "vitest run --project unit",
176662
+ test: "pnpm run test:unit && pnpm run test:integration",
176663
+ typecheck: "tsc"
176664
+ },
176665
+ devDependencies: {
176666
+ "@clack/prompts": "^0.11.0",
176667
+ "@types/node": "^25.0.7",
176668
+ "@types/semver": "^7.7.1",
176669
+ "@yao-pkg/pkg": "^6.15.0",
176670
+ "@zero/test-fixtures": "workspace:*",
176671
+ "@zeroxyz/sdk": "workspace:^",
176672
+ commander: "^13.0.0",
176673
+ open: "^11.0.0",
176674
+ "posthog-node": "^5.29.2",
176675
+ semver: "^7.8.5",
176676
+ tsup: "^8.5.1",
176677
+ tsx: "^4.21.0",
176678
+ typescript: "^5.9.3",
176679
+ viem: "^2.47.10",
176680
+ vitest: "^4.0.17",
176681
+ zod: "^4.3.5"
176682
+ }
176683
+ };
176420
176684
 
176421
176685
  // src/app.ts
176422
176686
  init_esm_shims();
@@ -178673,12 +178937,20 @@ var fetchCommand = (appContext) => new Command("fetch").description(
178673
178937
  process.exitCode = 1;
178674
178938
  return;
178675
178939
  }
178676
- const headers = {};
178940
+ const headers = {
178941
+ "user-agent": `zero-cli/${package_default2.version}`
178942
+ };
178677
178943
  if (options.header) {
178678
178944
  for (const h of options.header) {
178679
178945
  const colonIdx = h.indexOf(":");
178680
178946
  if (colonIdx > 0) {
178681
- headers[h.slice(0, colonIdx).trim()] = h.slice(colonIdx + 1).trim();
178947
+ const name = h.slice(0, colonIdx).trim();
178948
+ for (const existing of Object.keys(headers)) {
178949
+ if (existing !== name && existing.toLowerCase() === name.toLowerCase()) {
178950
+ delete headers[existing];
178951
+ }
178952
+ }
178953
+ headers[name] = h.slice(colonIdx + 1).trim();
178682
178954
  }
178683
178955
  }
178684
178956
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeroxyz/cli",
3
- "version": "1.31.0",
3
+ "version": "1.32.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "zero": "dist/index.js",