@sunasteriskrnd/takumi 1.0.0-dev.65 → 1.0.0-dev.66

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 +111 -11
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -19815,7 +19815,7 @@ var package_default;
19815
19815
  var init_package = __esm(() => {
19816
19816
  package_default = {
19817
19817
  name: "@sunasteriskrnd/takumi",
19818
- version: "1.0.0-dev.65",
19818
+ version: "1.0.0-dev.66",
19819
19819
  description: "CLI tool for bootstrapping and managing Takumi projects",
19820
19820
  type: "module",
19821
19821
  repository: {
@@ -20012,7 +20012,7 @@ function getLegacyManifestPath(providerRoot) {
20012
20012
  return join4(providerRoot, LEGACY_MANIFEST_FILENAME);
20013
20013
  }
20014
20014
  function getCliVersion() {
20015
- return "1.0.0-dev.65"?.trim() || process.env.npm_package_version?.trim() || "unknown";
20015
+ return "1.0.0-dev.66"?.trim() || process.env.npm_package_version?.trim() || "unknown";
20016
20016
  }
20017
20017
  function getCliUserAgent() {
20018
20018
  return `${TAKUMI_CLI_NPM_PACKAGE_NAME}/${getCliVersion()}`;
@@ -52980,6 +52980,9 @@ ${API_KEY_VAR}=${apiKey}
52980
52980
  writeFileSync(envPath, content, "utf-8");
52981
52981
  }
52982
52982
  // src/domains/takumi-api/api-error-handler.ts
52983
+ var LICENSE_REQUIRED_REMEDIATION = "Your Takumi license is inactive or expired. Contact your Sun* admin to renew access.";
52984
+ var LICENSE_REQUIRED_EXIT_CODE = 4;
52985
+
52983
52986
  class CkApiError extends Error {
52984
52987
  code;
52985
52988
  status;
@@ -53005,10 +53008,16 @@ function parseApiError(status, body) {
53005
53008
  const message = parsed?.message || parsed?.error || `API error (HTTP ${status})`;
53006
53009
  const retryAfter = parsed?.retryAfter;
53007
53010
  if (parsed?.code && isKnownErrorCode(parsed.code)) {
53008
- return new CkApiError(parsed.code, message, status, retryAfter);
53011
+ const code2 = parsed.code;
53012
+ return new CkApiError(code2, withRemediation(code2, message), status, retryAfter);
53009
53013
  }
53010
53014
  const code = mapStatusToErrorCode(status);
53011
- return new CkApiError(code, message, status, retryAfter);
53015
+ return new CkApiError(code, withRemediation(code, message), status, retryAfter);
53016
+ }
53017
+ function withRemediation(code, message) {
53018
+ if (code === "LICENSE_REQUIRED")
53019
+ return `${message} ${LICENSE_REQUIRED_REMEDIATION}`;
53020
+ return message;
53012
53021
  }
53013
53022
  function isKnownErrorCode(code) {
53014
53023
  const known = new Set([
@@ -80259,6 +80268,57 @@ function assetNameFor(kit) {
80259
80268
  return `takumi-${kit}-package.zip`;
80260
80269
  }
80261
80270
 
80271
+ class WorkerAssetError extends Error {
80272
+ status;
80273
+ reason;
80274
+ body;
80275
+ constructor(status2, reason, body) {
80276
+ super(`Worker asset fetch failed (HTTP ${status2}): ${reason}`);
80277
+ this.name = "WorkerAssetError";
80278
+ this.status = status2;
80279
+ this.reason = reason;
80280
+ this.body = body;
80281
+ }
80282
+ }
80283
+ async function parseWorkerAssetError(res) {
80284
+ let body = null;
80285
+ try {
80286
+ body = await res.json();
80287
+ } catch {
80288
+ body = null;
80289
+ }
80290
+ if (res.status === 404)
80291
+ return new WorkerAssetError(res.status, "NOT_FOUND", body);
80292
+ if (res.status === 503)
80293
+ return new WorkerAssetError(res.status, "TRANSIENT", body);
80294
+ if (res.status === 403 && body?.error === "LICENSE_REQUIRED") {
80295
+ return new WorkerAssetError(res.status, "LICENSE_REQUIRED", body);
80296
+ }
80297
+ return new WorkerAssetError(res.status, "UNKNOWN", body);
80298
+ }
80299
+
80300
+ class LicenseRequiredError extends Error {
80301
+ status = 403;
80302
+ reason;
80303
+ constructor(reason) {
80304
+ super(LICENSE_REQUIRED_REMEDIATION);
80305
+ this.name = "LicenseRequiredError";
80306
+ this.reason = reason ?? "no_license_or_entitlement";
80307
+ }
80308
+ }
80309
+ async function licenseErrorFromResponse(res) {
80310
+ if (res.status !== 403)
80311
+ return null;
80312
+ let body = null;
80313
+ try {
80314
+ body = await res.json();
80315
+ } catch {
80316
+ body = null;
80317
+ }
80318
+ if (body?.error === "LICENSE_REQUIRED")
80319
+ return new LicenseRequiredError(body.reason);
80320
+ return null;
80321
+ }
80262
80322
  class WorkerSource {
80263
80323
  serverUrl;
80264
80324
  kit;
@@ -80285,6 +80345,9 @@ class WorkerSource {
80285
80345
  if (res.status === 401)
80286
80346
  throw new NotLoggedInError;
80287
80347
  if (!res.ok) {
80348
+ const licenseError = await licenseErrorFromResponse(res);
80349
+ if (licenseError)
80350
+ throw licenseError;
80288
80351
  throw new Error(`Worker source: GET ${url} failed (HTTP ${res.status})`);
80289
80352
  }
80290
80353
  return ReleaseEntrySchema.parse(await res.json());
@@ -80296,6 +80359,9 @@ class WorkerSource {
80296
80359
  if (res.status === 401)
80297
80360
  throw new NotLoggedInError;
80298
80361
  if (!res.ok) {
80362
+ const licenseError = await licenseErrorFromResponse(res);
80363
+ if (licenseError)
80364
+ throw licenseError;
80299
80365
  throw new Error(`Worker source: GET ${url} failed (HTTP ${res.status})`);
80300
80366
  }
80301
80367
  const parsed = ReleaseListResponseSchema.parse(await res.json());
@@ -80310,6 +80376,9 @@ class WorkerSource {
80310
80376
  if (res.status === 404)
80311
80377
  throw new NotInIndexError(tag);
80312
80378
  if (!res.ok) {
80379
+ const licenseError = await licenseErrorFromResponse(res);
80380
+ if (licenseError)
80381
+ throw licenseError;
80313
80382
  throw new Error(`Worker source: GET ${url} failed (HTTP ${res.status})`);
80314
80383
  }
80315
80384
  return ReleaseEntrySchema.parse(await res.json());
@@ -80320,12 +80389,8 @@ class WorkerSource {
80320
80389
  const res = await fetch(url, { headers });
80321
80390
  if (res.status === 401)
80322
80391
  throw new NotLoggedInError;
80323
- if (res.status === 404) {
80324
- throw new Error(`Asset not found: ${this.kit}/${tag}/${asset}`);
80325
- }
80326
- if (!res.ok) {
80327
- throw new Error(`Worker source: GET ${url} failed (HTTP ${res.status})`);
80328
- }
80392
+ if (!res.ok)
80393
+ throw await parseWorkerAssetError(res);
80329
80394
  return res;
80330
80395
  }
80331
80396
  }
@@ -80642,6 +80707,11 @@ async function createVersionPrompt(kit, choices, _defaultIndex, allowManualEntry
80642
80707
  return selected;
80643
80708
  }
80644
80709
  async function handleSelectionError(error, kit, allowManualEntry, retryCallback) {
80710
+ if (error instanceof LicenseRequiredError) {
80711
+ le(VersionDisplayFormatter.formatError("License required", error.message), import_picocolors21.default.red("License Required"));
80712
+ process.exitCode = LICENSE_REQUIRED_EXIT_CODE;
80713
+ return null;
80714
+ }
80645
80715
  logger.error(`Version selection error: ${error.message}`);
80646
80716
  if (error.message.includes("401") || error.message.includes("403")) {
80647
80717
  le(VersionDisplayFormatter.formatError("Authentication failed", "Please check your GitHub token with: tkm auth"), import_picocolors21.default.red("Authentication Error"));
@@ -92909,6 +92979,36 @@ function getPackageVersion3() {
92909
92979
  return packageVersion2;
92910
92980
  }
92911
92981
 
92982
+ // src/domains/installation/release-source.ts
92983
+ init_auth_client();
92984
+ class WorkerAssetError2 extends Error {
92985
+ status;
92986
+ reason;
92987
+ body;
92988
+ constructor(status2, reason, body) {
92989
+ super(`Worker asset fetch failed (HTTP ${status2}): ${reason}`);
92990
+ this.name = "WorkerAssetError";
92991
+ this.status = status2;
92992
+ this.reason = reason;
92993
+ this.body = body;
92994
+ }
92995
+ }
92996
+ class LicenseRequiredError2 extends Error {
92997
+ status = 403;
92998
+ reason;
92999
+ constructor(reason) {
93000
+ super(LICENSE_REQUIRED_REMEDIATION);
93001
+ this.name = "LicenseRequiredError";
93002
+ this.reason = reason ?? "no_license_or_entitlement";
93003
+ }
93004
+ }
93005
+ function isLicenseRequired(error) {
93006
+ return error instanceof LicenseRequiredError2 || error instanceof WorkerAssetError2 && error.reason === "LICENSE_REQUIRED";
93007
+ }
93008
+
93009
+ // src/domains/takumi-api/api-error-handler.ts
93010
+ var LICENSE_REQUIRED_EXIT_CODE2 = 4;
93011
+
92912
93012
  // src/shared/logger.ts
92913
93013
  init_output_manager();
92914
93014
  var import_picocolors34 = __toESM(require_picocolors(), 1);
@@ -93352,7 +93452,7 @@ var parsed = cli.parse(process.argv, { run: false });
93352
93452
  }
93353
93453
  } catch (error) {
93354
93454
  console.error("CLI error:", error instanceof Error ? error.message : error);
93355
- process.exitCode = 1;
93455
+ process.exitCode = isLicenseRequired(error) ? LICENSE_REQUIRED_EXIT_CODE2 : 1;
93356
93456
  if (output2.isJson()) {
93357
93457
  await output2.flushJson();
93358
93458
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sunasteriskrnd/takumi",
3
- "version": "1.0.0-dev.65",
3
+ "version": "1.0.0-dev.66",
4
4
  "description": "CLI tool for bootstrapping and managing Takumi projects",
5
5
  "type": "module",
6
6
  "repository": {