@weavix/cli 0.7.0 → 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.js CHANGED
@@ -58,9 +58,6 @@ var impl, CLI_NAME2, CLI_DESCRIPTION2, CLI_HELP_TEXT2, CREATE_SERVICES2, init_me
58
58
  });
59
59
 
60
60
  // src/core/cliConfig/manager.ts
61
- function getConfigPath() {
62
- return CONFIG_FILE;
63
- }
64
61
  function readConfig() {
65
62
  if (cached !== void 0)
66
63
  return cached;
@@ -76,9 +73,6 @@ function readConfig() {
76
73
  function writeConfig(config) {
77
74
  (0, import_fs.existsSync)(CONFIG_DIR) || (0, import_fs.mkdirSync)(CONFIG_DIR, { recursive: !0, mode: 448 }), (0, import_fs.writeFileSync)(CONFIG_FILE, JSON.stringify(config, null, 2), { mode: 384 }), cached = config;
78
75
  }
79
- function clearConfig() {
80
- (0, import_fs.existsSync)(CONFIG_FILE) && (0, import_fs.rmSync)(CONFIG_FILE), cached = null;
81
- }
82
76
  var import_fs, os, import_path, CONFIG_DIR, CONFIG_FILE, cached, init_manager = __esm({
83
77
  "src/core/cliConfig/manager.ts"() {
84
78
  "use strict";
@@ -86,94 +80,6 @@ var import_fs, os, import_path, CONFIG_DIR, CONFIG_FILE, cached, init_manager =
86
80
  }
87
81
  });
88
82
 
89
- // src/core/doctor/policy.ts
90
- function createDoctorPolicy(options) {
91
- let publish = !!options.publish, publishOnlyStatus = publish ? "fail" : "warn";
92
- return {
93
- mode: publish ? "publish" : "debug",
94
- marketplaceAssetsStatus: publishOnlyStatus,
95
- manifestPermissionsStatus: publishOnlyStatus,
96
- manifestSupportStatus: publishOnlyStatus,
97
- distMissingStatus: publishOnlyStatus,
98
- authMissingStatus: publishOnlyStatus
99
- };
100
- }
101
- var init_policy = __esm({
102
- "src/core/doctor/policy.ts"() {
103
- "use strict";
104
- }
105
- });
106
-
107
- // src/core/doctor/report.ts
108
- function createDoctorReport() {
109
- return {
110
- ok: !1,
111
- summary: {
112
- passed: 0,
113
- warnings: 0,
114
- failures: 0
115
- },
116
- checks: []
117
- };
118
- }
119
- function addCheck(report, check) {
120
- report.checks.push({
121
- ...check,
122
- status: check.status || "pass"
123
- });
124
- }
125
- function updateSummary(report) {
126
- let passed = report.checks.filter((check) => check.status === "pass").length, warnings = report.checks.filter((check) => check.status === "warn").length, failures = report.checks.filter((check) => check.status === "fail").length;
127
- report.summary = {
128
- passed,
129
- warnings,
130
- failures
131
- }, report.ok = failures === 0;
132
- }
133
- function statusBadge(status) {
134
- let display = STATUS_DISPLAY[status];
135
- return `${display.icon} [${display.label}]`;
136
- }
137
- function formatReport(report) {
138
- let lines = ["Tracker Plugin Doctor", ""];
139
- report.distribution && lines.push(`Distribution: ${report.distribution}`), report.mode && lines.push(`Mode: ${report.mode}`), report.projectRoot && lines.push(`Project root: ${report.projectRoot}`), report.manifestPath && lines.push(`Manifest path: ${report.manifestPath}`), report.manifest && lines.push(`Manifest: ${report.manifest.slug}@${report.manifest.version}`), report.packageManager && lines.push(`Package manager: ${report.packageManager}`), lines.push("", "Checks:");
140
- for (let check of report.checks)
141
- lines.push(` ${statusBadge(check.status)} ${check.title}: ${check.message}`), check.action && lines.push(` Action: ${check.action}`);
142
- return lines.push(
143
- "",
144
- `Summary: \u2713 ${report.summary.passed} passed, \u26A0 ${report.summary.warnings} warning(s), \u2717 ${report.summary.failures} failure(s).`
145
- ), lines.push(
146
- report.ok ? report.summary.warnings > 0 ? "\u26A0 Doctor finished with warnings." : "\u2713 Doctor finished successfully." : report.mode === "publish" ? "\u2717 Doctor failed. Fix failed checks before publishing." : "\u2717 Doctor failed. Fix failed checks before local debug or build."
147
- ), `${lines.join(`
148
- `)}
149
- `;
150
- }
151
- function writeStdout(content) {
152
- return new Promise((resolve2, reject) => {
153
- process.stdout.write(content, (error2) => {
154
- if (error2) {
155
- reject(error2);
156
- return;
157
- }
158
- resolve2();
159
- });
160
- });
161
- }
162
- async function finishDoctor(report, options) {
163
- updateSummary(report), await writeStdout(options.json ? `${JSON.stringify(report, null, 4)}
164
- ` : formatReport(report)), report.ok || (process.exitCode = 1);
165
- }
166
- var STATUS_DISPLAY, init_report = __esm({
167
- "src/core/doctor/report.ts"() {
168
- "use strict";
169
- STATUS_DISPLAY = {
170
- pass: { icon: "\u2713", label: "PASS" },
171
- warn: { icon: "\u26A0", label: "WARN" },
172
- fail: { icon: "\u2717", label: "FAIL" }
173
- };
174
- }
175
- });
176
-
177
83
  // src/core/auth/keyringAuthStorage.ts
178
84
  var fs, import_keyring, parseAuthData, readLegacyAuthData, removeLegacyAuthData, createKeyringAuthStorage, init_keyringAuthStorage = __esm({
179
85
  "src/core/auth/keyringAuthStorage.ts"() {
@@ -257,85 +163,314 @@ var os2, path2, authFile, authStorage, getToken, externalAuthManager, init_authM
257
163
  }
258
164
  });
259
165
 
166
+ // src/distributions/external/auth.ts
167
+ var auth_exports = {};
168
+ __export(auth_exports, {
169
+ getAuthHeader: () => getAuthHeader,
170
+ getPlatformHeaders: () => getPlatformHeaders
171
+ });
172
+ function getAuthHeader() {
173
+ let token = externalAuthManager.token;
174
+ return token ? `OAuth ${token}` : null;
175
+ }
176
+ function getPlatformHeaders() {
177
+ let orgId = readConfig()?.api?.platformOrgId;
178
+ return orgId ? { "X-Org-ID": orgId } : {};
179
+ }
180
+ var init_auth = __esm({
181
+ "src/distributions/external/auth.ts"() {
182
+ "use strict";
183
+ init_manager();
184
+ init_authManager();
185
+ }
186
+ });
187
+
188
+ // src/distribution/auth.ts
189
+ var impl2, getAuthHeader2, getPlatformHeaders2, init_auth2 = __esm({
190
+ "src/distribution/auth.ts"() {
191
+ "use strict";
192
+ init_flag();
193
+ impl2 = (init_auth(), __toCommonJS(auth_exports)), { getAuthHeader: getAuthHeader2, getPlatformHeaders: getPlatformHeaders2 } = impl2;
194
+ }
195
+ });
196
+
197
+ // src/utils/verbose.ts
198
+ function setVerboseEnabled(value) {
199
+ verboseEnabled = value;
200
+ }
201
+ function isVerboseEnabled() {
202
+ return verboseEnabled;
203
+ }
204
+ function writeVerboseArtifact(relativePath, content) {
205
+ let targetPath = import_path2.default.resolve(".yaweavix-debug", relativePath);
206
+ return import_fs2.default.mkdirSync(import_path2.default.dirname(targetPath), { recursive: !0 }), import_fs2.default.writeFileSync(targetPath, content), targetPath;
207
+ }
208
+ var import_fs2, import_path2, verboseEnabled, init_verbose = __esm({
209
+ "src/utils/verbose.ts"() {
210
+ "use strict";
211
+ import_fs2 = __toESM(require("fs")), import_path2 = __toESM(require("path")), verboseEnabled = !1;
212
+ }
213
+ });
214
+
215
+ // src/utils/logger.ts
216
+ function success(message) {
217
+ console.info(import_picocolors.default.green(`\u2705 ${message}`)), newLine();
218
+ }
219
+ function error(messageOrErr, err) {
220
+ let message = messageOrErr instanceof Error ? messageOrErr.message : messageOrErr;
221
+ console.error(import_picocolors.default.red(`\u274C ${message}`)), err instanceof Error && console.error(import_picocolors.default.red(err.message)), newLine();
222
+ }
223
+ function warning(message) {
224
+ console.warn(import_picocolors.default.yellow(`\u26A0\uFE0F ${message}`)), newLine();
225
+ }
226
+ function info(message) {
227
+ console.info(message), newLine();
228
+ }
229
+ function verbose(message) {
230
+ isVerboseEnabled() && (console.info(import_picocolors.default.dim(message)), newLine());
231
+ }
232
+ function suggest(command) {
233
+ console.info(`Run: ${command}`), newLine();
234
+ }
235
+ function newLine(count = 1) {
236
+ console.info(`
237
+ `.repeat(count - 1));
238
+ }
239
+ function separator(char = "\u2500", length = 60) {
240
+ console.info(import_picocolors.default.dim(char.repeat(length))), newLine();
241
+ }
242
+ function commands(title, data) {
243
+ newLine(), title && (console.info(import_picocolors.default.bold(import_picocolors.default.cyan(`${title}:`))), newLine()), data.forEach((cmd) => {
244
+ console.info(import_picocolors.default.dim(" $ ") + import_picocolors.default.white(cmd));
245
+ }), newLine();
246
+ }
247
+ var import_picocolors, logger, logger_default, init_logger = __esm({
248
+ "src/utils/logger.ts"() {
249
+ "use strict";
250
+ import_picocolors = __toESM(require("picocolors"));
251
+ init_verbose();
252
+ logger = {
253
+ success,
254
+ error,
255
+ warning,
256
+ info,
257
+ verbose,
258
+ suggest,
259
+ newLine,
260
+ separator,
261
+ commands
262
+ }, logger_default = logger;
263
+ }
264
+ });
265
+
260
266
  // src/distributions/external/hosts.ts
261
267
  var hosts_exports = {};
262
268
  __export(hosts_exports, {
263
- getBuckets: () => getBuckets,
264
- getMdsEndpoint: () => getMdsEndpoint,
265
269
  getOAuthTokenUrl: () => getOAuthTokenUrl,
266
270
  getPlatformApiPrefix: () => getPlatformApiPrefix,
267
271
  getPlatformBaseUrl: () => getPlatformBaseUrl,
268
272
  getPluginDownloadBase: () => getPluginDownloadBase,
269
- getS3Endpoint: () => getS3Endpoint,
270
- getS3Region: () => getS3Region,
271
- getTrackerBaseUrl: () => getTrackerBaseUrl,
272
273
  getUpdateCheckInfo: () => getUpdateCheckInfo
273
274
  });
274
- function requireConfig() {
275
- let cfg = readConfig();
276
- if (!cfg)
277
- throw new Error('CLI is not configured. Run "weavix config set" to configure.');
278
- return cfg;
279
- }
280
- function getS3Endpoint() {
281
- let cfg = requireConfig();
282
- if (!cfg.s3?.endpoint)
283
- throw new Error('S3 endpoint is not configured. Run "weavix config set" to configure.');
284
- return cfg.s3.endpoint;
285
- }
286
- function getMdsEndpoint() {
287
- let cfg = requireConfig();
288
- if (!cfg.mds?.endpoint)
289
- throw new Error('MDS endpoint is not configured. Run "weavix config set" to configure.');
290
- return cfg.mds.endpoint;
291
- }
292
- function getS3Region() {
293
- let cfg = requireConfig();
294
- if (!cfg.s3?.region)
295
- throw new Error('S3 region is not configured. Run "weavix config set" to configure.');
296
- return cfg.s3.region;
297
- }
298
- function getBuckets() {
299
- let production = requireConfig().buckets?.production;
300
- if (!production?.static || !production?.config)
301
- throw new Error('S3 buckets are not configured. Run "weavix config set" to configure.');
302
- let prod = { static: production.static, config: production.config };
303
- return { testing: prod, production: prod };
304
- }
305
275
  function getPluginDownloadBase(env) {
306
276
  if (env === "debug")
307
- return "http://localhost:5173/plugins-debug";
308
- let base = requireConfig().pluginDownloadBase?.production;
309
- if (!base)
310
- throw new Error(
311
- 'Plugin download base is not configured. Run "weavix config set" to configure.'
312
- );
313
- return base;
277
+ return PLUGIN_DEBUG_DOWNLOAD_BASE;
278
+ throw new Error(`Plugin download base is not available for environment "${env}".`);
279
+ }
280
+ function normalizeBaseUrl(value) {
281
+ return value.replace(/\/+$/, "");
314
282
  }
315
283
  function getPlatformBaseUrl() {
316
- return readConfig()?.api?.platformBaseUrl ?? PLATFORM_BASE_URL;
284
+ let envOverride = process.env[PLATFORM_BASE_URL_ENV]?.trim();
285
+ return envOverride ? normalizeBaseUrl(envOverride) : PLATFORM_BASE_URL;
317
286
  }
318
287
  function getPlatformApiPrefix() {
319
288
  return "/api/cli/v1";
320
289
  }
321
- function getTrackerBaseUrl() {
322
- return TRACKER_BASE_URL;
323
- }
324
290
  function getOAuthTokenUrl() {
325
- return readConfig()?.auth?.oauthUrl ?? OAUTH_TOKEN_URL;
291
+ return OAUTH_TOKEN_URL;
326
292
  }
327
293
  function getUpdateCheckInfo() {
328
294
  return null;
329
295
  }
330
- var TRACKER_BASE_URL, PLATFORM_BASE_URL, OAUTH_TOKEN_URL, init_hosts = __esm({
296
+ var PLATFORM_BASE_URL, PLATFORM_BASE_URL_ENV, OAUTH_TOKEN_URL, PLUGIN_DEBUG_DOWNLOAD_BASE, init_hosts = __esm({
331
297
  "src/distributions/external/hosts.ts"() {
332
298
  "use strict";
333
- init_manager();
334
- TRACKER_BASE_URL = "https://api.tracker.yandex.net/v3", PLATFORM_BASE_URL = "https://plugins.cli-api.tracker.yandex.net", OAUTH_TOKEN_URL = "https://oauth.yandex.ru/authorize?response_type=token&client_id=f57901dffe3849cbb3dbb5f616158e28";
299
+ PLATFORM_BASE_URL = "https://plugins.cli-api.tracker.yandex.net", PLATFORM_BASE_URL_ENV = "TRACKER_CLI_PLATFORM_BASE_URL", OAUTH_TOKEN_URL = "https://oauth.yandex.ru/authorize?response_type=token&client_id=f57901dffe3849cbb3dbb5f616158e28", PLUGIN_DEBUG_DOWNLOAD_BASE = "http://localhost:5173/plugins-debug";
300
+ }
301
+ });
302
+
303
+ // src/distribution/hosts.ts
304
+ var impl3, getS3Endpoint, getMdsEndpoint, getS3Region, getBuckets, getPluginDownloadBase2, getPlatformBaseUrl2, getPlatformApiPrefix2, getTrackerBaseUrl, getOAuthTokenUrl2, getUpdateCheckInfo2, init_hosts2 = __esm({
305
+ "src/distribution/hosts.ts"() {
306
+ "use strict";
307
+ init_flag();
308
+ impl3 = (init_hosts(), __toCommonJS(hosts_exports)), {
309
+ getS3Endpoint,
310
+ getMdsEndpoint,
311
+ getS3Region,
312
+ getBuckets,
313
+ getPluginDownloadBase: getPluginDownloadBase2,
314
+ getPlatformBaseUrl: getPlatformBaseUrl2,
315
+ getPlatformApiPrefix: getPlatformApiPrefix2,
316
+ getTrackerBaseUrl,
317
+ getOAuthTokenUrl: getOAuthTokenUrl2,
318
+ getUpdateCheckInfo: getUpdateCheckInfo2
319
+ } = impl3;
320
+ }
321
+ });
322
+
323
+ // src/api/constants.ts
324
+ var mockedCategories, init_constants = __esm({
325
+ "src/api/constants.ts"() {
326
+ "use strict";
327
+ init_hosts2();
328
+ init_hosts2();
329
+ mockedCategories = {
330
+ items: [
331
+ {
332
+ slug: "integrations",
333
+ name: {
334
+ ru: "\u0418\u043D\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438",
335
+ en: "Integrations"
336
+ }
337
+ },
338
+ {
339
+ slug: "analytics",
340
+ name: {
341
+ ru: "\u0410\u043D\u0430\u043B\u0438\u0442\u0438\u043A\u0430",
342
+ en: "Analytics"
343
+ }
344
+ },
345
+ {
346
+ slug: "planning",
347
+ name: {
348
+ ru: "\u041F\u043B\u0430\u043D\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u0435",
349
+ en: "Planning"
350
+ }
351
+ },
352
+ {
353
+ slug: "development",
354
+ name: {
355
+ ru: "\u0420\u0430\u0437\u0440\u0430\u0431\u043E\u0442\u043A\u0430",
356
+ en: "Development"
357
+ }
358
+ },
359
+ {
360
+ slug: "automations",
361
+ name: {
362
+ ru: "\u0410\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438",
363
+ en: "Automations"
364
+ }
365
+ },
366
+ {
367
+ slug: "productivity",
368
+ name: {
369
+ ru: "\u041F\u0440\u043E\u0434\u0443\u043A\u0442\u0438\u0432\u043D\u043E\u0441\u0442\u044C",
370
+ en: "Productivity"
371
+ }
372
+ },
373
+ {
374
+ slug: "entertainment",
375
+ name: {
376
+ ru: "\u0420\u0430\u0437\u0432\u043B\u0435\u0447\u0435\u043D\u0438\u044F",
377
+ en: "Entertainment"
378
+ }
379
+ },
380
+ {
381
+ slug: "ai-assistants",
382
+ name: {
383
+ ru: "\u0418\u0418-\u043F\u043E\u043C\u043E\u0449\u043D\u0438\u043A\u0438",
384
+ en: "AI Assistants"
385
+ }
386
+ },
387
+ {
388
+ slug: "support",
389
+ name: {
390
+ ru: "\u041F\u043E\u0434\u0434\u0435\u0440\u0436\u043A\u0430",
391
+ en: "Support"
392
+ }
393
+ },
394
+ {
395
+ slug: "security",
396
+ name: {
397
+ ru: "\u0411\u0435\u0437\u043E\u043F\u0430\u0441\u043D\u043E\u0441\u0442\u044C",
398
+ en: "Security"
399
+ }
400
+ }
401
+ ]
402
+ };
403
+ }
404
+ });
405
+
406
+ // src/api/requestDebug.ts
407
+ function redactHeaders(headers) {
408
+ let result = {};
409
+ for (let [key, value] of Object.entries(headers))
410
+ if (key.toLowerCase() === "authorization") {
411
+ let [scheme] = value.split(" ");
412
+ result[key] = scheme ? `${scheme} ${REDACTED}` : REDACTED;
413
+ } else
414
+ result[key] = value;
415
+ return result;
416
+ }
417
+ function formatDebugBody(body, formData) {
418
+ if (formData) {
419
+ let size = "";
420
+ try {
421
+ let length = formData.getLengthSync?.();
422
+ typeof length == "number" && (size = `, ~${length} bytes`);
423
+ } catch {
424
+ }
425
+ return `[multipart/form-data${size}] (binary body, e.g. plugin archive \u2014 not dumped)`;
426
+ }
427
+ return typeof body == "string" ? body : "(none)";
428
+ }
429
+ function buildFailureDebug(params) {
430
+ let { method, url, status, headers, body, formData } = params;
431
+ return [
432
+ "Platform API request failed \u2014 debug info (Authorization redacted):",
433
+ ` method: ${method}`,
434
+ ` url: ${url}`,
435
+ ` status: ${status ?? "(no HTTP response \u2014 network/transport error)"}`,
436
+ ` headers: ${JSON.stringify(redactHeaders(headers), null, 2)}`,
437
+ ` body: ${formatDebugBody(body, formData)}`
438
+ ].join(`
439
+ `);
440
+ }
441
+ var REDACTED, init_requestDebug = __esm({
442
+ "src/api/requestDebug.ts"() {
443
+ "use strict";
444
+ REDACTED = "****redacted****";
335
445
  }
336
446
  });
337
447
 
338
- // src/distributions/external/trackerApiRequest.ts
448
+ // src/api/platformApiRequest.ts
449
+ function setPlatformIamToken(token) {
450
+ platformIamToken = token?.trim() || void 0;
451
+ }
452
+ function buildRequestHeaders(headers, formData) {
453
+ let authHeader = getAuthHeader2();
454
+ if (!platformIamToken && !authHeader)
455
+ throw new Error(`Not authenticated. Run "${CLI_NAME2} login" first.`);
456
+ let requestHeaders = {
457
+ Accept: "*/*",
458
+ ...platformIamToken ? { "x-iam-token": platformIamToken } : { Authorization: authHeader },
459
+ ...getPlatformHeaders2(),
460
+ ...headers
461
+ };
462
+ return formData || (requestHeaders["Content-Type"] = "application/json"), requestHeaders;
463
+ }
464
+ function buildRequestBody(method, body, formData) {
465
+ if (formData) {
466
+ let formHeaders = formData.getHeaders?.();
467
+ return {
468
+ body: formData,
469
+ headers: formHeaders || {}
470
+ };
471
+ }
472
+ return body && method !== "GET" ? { body: JSON.stringify(body) } : {};
473
+ }
339
474
  function buildQueryString(queryParams) {
340
475
  if (!queryParams || Object.keys(queryParams).length === 0)
341
476
  return "";
@@ -347,102 +482,185 @@ function buildQueryString(queryParams) {
347
482
  async function parseResponse(response) {
348
483
  return response.status === 204 || response.headers.get("content-length") === "0" ? void 0 : response.headers.get("content-type")?.includes("application/json") ? await response.json() : await response.text();
349
484
  }
350
- async function externalTrackerApiRequest(endpoint, options = {}) {
351
- let { method = "GET", body, headers = {}, formData, queryParams } = options, token = externalAuthManager.token;
352
- if (!token)
353
- throw new Error(`Not authenticated. Run "${CLI_NAME} login" first.`);
354
- let requestHeaders = {
355
- Authorization: `OAuth ${token}`,
356
- "X-Org-ID": ORG_ID,
357
- Accept: "application/json",
358
- ...headers
359
- }, requestBody;
360
- if (formData) {
361
- let formHeaders = formData.getHeaders?.();
362
- Object.assign(requestHeaders, formHeaders), requestBody = formData;
363
- } else body && method !== "GET" && (requestHeaders["Content-Type"] = "application/json", requestBody = JSON.stringify(body));
364
- let queryString = buildQueryString(queryParams), url = `${TRACKER_BASE_URL2}${endpoint}${queryString}`, response = await (0, import_node_fetch.default)(url, {
485
+ async function platformApiRequest(endpoint, options = {}) {
486
+ let { method = "GET", body, headers = {}, formData, queryParams } = options, requestHeaders = buildRequestHeaders(headers, formData), { body: requestBody, headers: additionalHeaders } = buildRequestBody(
365
487
  method,
366
- headers: requestHeaders,
488
+ body,
489
+ formData
490
+ ), requestOptions = {
491
+ method,
492
+ headers: { ...requestHeaders, ...additionalHeaders },
367
493
  body: requestBody
368
- });
369
- if (!response.ok) {
370
- let errorText = await response.text(), errorMessage = `Tracker API error ${response.status}: ${errorText}`;
371
- try {
372
- let errorJson = JSON.parse(errorText);
373
- errorJson.message && (errorMessage = `Tracker API error ${response.status}: ${errorJson.message}`);
374
- } catch {
494
+ }, queryString = buildQueryString(queryParams), url = `${getPlatformBaseUrl2()}${getPlatformApiPrefix2()}${endpoint}${queryString}`, controller = new AbortController(), timeout = setTimeout(() => controller.abort(), PLATFORM_API_TIMEOUT_MS), responseStatus;
495
+ if (isVerboseEnabled() && (logger_default.info(
496
+ `[platform-api-debug] Request: method=${method} url=${url} hasBody=${!!body} hasFormData=${!!formData} timeoutMs=${PLATFORM_API_TIMEOUT_MS}`
497
+ ), body !== void 0 && logger_default.info(`[platform-api-debug] Request body: ${JSON.stringify(body)}`), formData)) {
498
+ let debugPath = writeVerboseArtifact(
499
+ "requests/latest-form-data.txt",
500
+ `method=${method}
501
+ url=${url}
502
+ headers=${JSON.stringify({ ...requestHeaders, ...additionalHeaders }, null, 2)}
503
+ formData=present
504
+ `
505
+ );
506
+ logger_default.info(`[platform-api-debug] Saved form-data request metadata to ${debugPath}`);
507
+ }
508
+ try {
509
+ let response = await (0, import_node_fetch.default)(url, {
510
+ ...requestOptions,
511
+ signal: controller.signal
512
+ });
513
+ if (responseStatus = response.status, isVerboseEnabled() && logger_default.info(
514
+ `[platform-api-debug] Response: method=${method} url=${url} status=${response.status} contentType=${response.headers.get("content-type") ?? "n/a"}`
515
+ ), !response.ok) {
516
+ let errorText = await response.text(), errorMessage = errorText;
517
+ try {
518
+ let errorJson = JSON.parse(errorText);
519
+ errorJson.message && (errorMessage = errorJson.message);
520
+ } catch {
521
+ }
522
+ throw new Error(`HTTP ${response.status} ${response.statusText}: ${errorMessage}`);
375
523
  }
376
- throw new Error(errorMessage);
524
+ return parseResponse(response);
525
+ } catch (error2) {
526
+ throw logger_default.error(
527
+ buildFailureDebug({
528
+ method,
529
+ url,
530
+ status: responseStatus,
531
+ headers: requestOptions.headers,
532
+ body: requestBody,
533
+ formData
534
+ })
535
+ ), error2 instanceof Error && error2.name === "AbortError" ? new Error(
536
+ `Platform API request timed out after ${PLATFORM_API_TIMEOUT_MS}ms: ${method} ${url}`
537
+ ) : error2;
538
+ } finally {
539
+ clearTimeout(timeout);
377
540
  }
378
- return parseResponse(response);
379
541
  }
380
- var import_node_fetch, TRACKER_BASE_URL2, ORG_ID, init_trackerApiRequest = __esm({
381
- "src/distributions/external/trackerApiRequest.ts"() {
542
+ var import_node_fetch, PLATFORM_API_TIMEOUT_MS, platformIamToken, init_platformApiRequest = __esm({
543
+ "src/api/platformApiRequest.ts"() {
382
544
  "use strict";
383
545
  import_node_fetch = __toESM(require("node-fetch"));
384
- init_authManager();
385
- init_meta();
386
- TRACKER_BASE_URL2 = "https://api.tracker.yandex.net/v3", ORG_ID = "8470884";
546
+ init_auth2();
547
+ init_meta2();
548
+ init_logger();
549
+ init_verbose();
550
+ init_constants();
551
+ init_requestDebug();
552
+ PLATFORM_API_TIMEOUT_MS = Number(process.env.TRACKER_CLI_PLATFORM_TIMEOUT_MS || 3e4);
387
553
  }
388
554
  });
389
555
 
390
- // src/distributions/external/doctorChecks.ts
391
- var doctorChecks_exports = {};
392
- __export(doctorChecks_exports, {
393
- checkDistribution: () => checkDistribution
556
+ // src/api/user.ts
557
+ async function verifyToken() {
558
+ try {
559
+ return await platformApiRequest("/plugins/my", { method: "GET" }), !0;
560
+ } catch {
561
+ return !1;
562
+ }
563
+ }
564
+ var init_user = __esm({
565
+ "src/api/user.ts"() {
566
+ "use strict";
567
+ init_platformApiRequest();
568
+ }
394
569
  });
395
- function checkCliConfig(report) {
396
- let config = readConfig(), configPath = getConfigPath();
397
- if (config) {
398
- addCheck(report, {
399
- id: "distribution.config",
400
- title: "CLI config",
401
- message: `External CLI config is readable at ${configPath}.`,
402
- data: {
403
- configPath
404
- }
405
- });
406
- return;
570
+
571
+ // src/core/doctor/policy.ts
572
+ function createDoctorPolicy(options) {
573
+ let publish = !!options.publish, publishOnlyStatus = publish ? "fail" : "warn";
574
+ return {
575
+ mode: publish ? "publish" : "debug",
576
+ marketplaceAssetsStatus: publishOnlyStatus,
577
+ manifestPermissionsStatus: publishOnlyStatus,
578
+ manifestSupportStatus: publishOnlyStatus,
579
+ distMissingStatus: publishOnlyStatus,
580
+ authMissingStatus: publishOnlyStatus
581
+ };
582
+ }
583
+ var init_policy = __esm({
584
+ "src/core/doctor/policy.ts"() {
585
+ "use strict";
407
586
  }
408
- addCheck(report, {
409
- id: "distribution.config",
410
- title: "CLI config",
411
- status: "fail",
412
- message: `External CLI config is missing at ${configPath}.`,
413
- action: "Run weavix config set before using external distribution commands.",
414
- data: {
415
- configPath
416
- }
587
+ });
588
+
589
+ // src/core/doctor/report.ts
590
+ function createDoctorReport() {
591
+ return {
592
+ ok: !1,
593
+ summary: {
594
+ passed: 0,
595
+ warnings: 0,
596
+ failures: 0
597
+ },
598
+ checks: []
599
+ };
600
+ }
601
+ function addCheck(report, check) {
602
+ report.checks.push({
603
+ ...check,
604
+ status: check.status || "pass"
417
605
  });
418
606
  }
419
- function checkHostResolution(report) {
420
- try {
421
- let data = {
422
- trackerBaseUrl: getTrackerBaseUrl(),
423
- platformBaseUrl: getPlatformBaseUrl(),
424
- s3Endpoint: getS3Endpoint(),
425
- mdsEndpoint: getMdsEndpoint(),
426
- s3Region: getS3Region(),
427
- buckets: getBuckets(),
428
- pluginDownloadBase: getPluginDownloadBase("production")
429
- };
430
- addCheck(report, {
431
- id: "distribution.hosts",
432
- title: "External host configuration",
433
- message: "External host configuration resolved.",
434
- data
435
- });
436
- } catch (error2) {
437
- addCheck(report, {
438
- id: "distribution.hosts",
439
- title: "External host configuration",
440
- status: "fail",
441
- message: error2 instanceof Error ? error2.message : String(error2),
442
- action: "Run weavix config set and fill required endpoints."
607
+ function updateSummary(report) {
608
+ let passed = report.checks.filter((check) => check.status === "pass").length, warnings = report.checks.filter((check) => check.status === "warn").length, failures = report.checks.filter((check) => check.status === "fail").length;
609
+ report.summary = {
610
+ passed,
611
+ warnings,
612
+ failures
613
+ }, report.ok = failures === 0;
614
+ }
615
+ function statusBadge(status) {
616
+ let display = STATUS_DISPLAY[status];
617
+ return `${display.icon} [${display.label}]`;
618
+ }
619
+ function formatReport(report) {
620
+ let lines = ["Tracker Plugin Doctor", ""];
621
+ report.distribution && lines.push(`Distribution: ${report.distribution}`), report.mode && lines.push(`Mode: ${report.mode}`), report.projectRoot && lines.push(`Project root: ${report.projectRoot}`), report.manifestPath && lines.push(`Manifest path: ${report.manifestPath}`), report.manifest && lines.push(`Manifest: ${report.manifest.slug}@${report.manifest.version}`), report.packageManager && lines.push(`Package manager: ${report.packageManager}`), lines.push("", "Checks:");
622
+ for (let check of report.checks)
623
+ lines.push(` ${statusBadge(check.status)} ${check.title}: ${check.message}`), check.action && lines.push(` Action: ${check.action}`);
624
+ return lines.push(
625
+ "",
626
+ `Summary: \u2713 ${report.summary.passed} passed, \u26A0 ${report.summary.warnings} warning(s), \u2717 ${report.summary.failures} failure(s).`
627
+ ), lines.push(
628
+ report.ok ? report.summary.warnings > 0 ? "\u26A0 Doctor finished with warnings." : "\u2713 Doctor finished successfully." : report.mode === "publish" ? "\u2717 Doctor failed. Fix failed checks before publishing." : "\u2717 Doctor failed. Fix failed checks before local debug or build."
629
+ ), `${lines.join(`
630
+ `)}
631
+ `;
632
+ }
633
+ function writeStdout(content) {
634
+ return new Promise((resolve2, reject) => {
635
+ process.stdout.write(content, (error2) => {
636
+ if (error2) {
637
+ reject(error2);
638
+ return;
639
+ }
640
+ resolve2();
443
641
  });
642
+ });
643
+ }
644
+ async function finishDoctor(report, options) {
645
+ updateSummary(report), await writeStdout(options.json ? `${JSON.stringify(report, null, 4)}
646
+ ` : formatReport(report)), report.ok || (process.exitCode = 1);
647
+ }
648
+ var STATUS_DISPLAY, init_report = __esm({
649
+ "src/core/doctor/report.ts"() {
650
+ "use strict";
651
+ STATUS_DISPLAY = {
652
+ pass: { icon: "\u2713", label: "PASS" },
653
+ warn: { icon: "\u26A0", label: "WARN" },
654
+ fail: { icon: "\u2717", label: "FAIL" }
655
+ };
444
656
  }
445
- }
657
+ });
658
+
659
+ // src/distributions/external/doctorChecks.ts
660
+ var doctorChecks_exports = {};
661
+ __export(doctorChecks_exports, {
662
+ checkDistribution: () => checkDistribution
663
+ });
446
664
  async function checkExternalAuth(report, {
447
665
  required,
448
666
  useNetwork
@@ -468,25 +686,29 @@ async function checkExternalAuth(report, {
468
686
  data: {
469
687
  storage: "system credential store"
470
688
  }
471
- }), !!useNetwork)
472
- try {
473
- await externalTrackerApiRequest("/myself"), addCheck(report, {
474
- id: "auth.tracker.network",
475
- title: "Tracker auth network",
476
- message: "Verified external Tracker auth with /myself."
477
- });
478
- } catch (error2) {
479
- addCheck(report, {
480
- id: "auth.tracker.network",
481
- title: "Tracker auth network",
482
- status: "fail",
483
- message: error2 instanceof Error ? error2.message : String(error2),
484
- action: "Check network access, org access, and rerun weavix login."
485
- });
486
- }
689
+ }), readConfig()?.api?.platformOrgId ? addCheck(report, {
690
+ id: "auth.organization",
691
+ title: "Organization ID",
692
+ message: "Organization ID is configured."
693
+ }) : addCheck(report, {
694
+ id: "auth.organization",
695
+ title: "Organization ID",
696
+ status: authStatus,
697
+ message: "Organization ID is not configured.",
698
+ action: "Run weavix login to set your Organization ID."
699
+ }), !useNetwork)
700
+ return;
701
+ let isValid = await verifyToken();
702
+ addCheck(report, {
703
+ id: "auth.platform.network",
704
+ title: "Platform auth network",
705
+ status: isValid ? "pass" : "fail",
706
+ message: isValid ? "Verified Platform auth successfully." : "Platform auth verification failed.",
707
+ ...isValid ? {} : { action: "Check network access, org access, and rerun weavix login." }
708
+ });
487
709
  }
488
710
  async function checkDistribution(report, _projectRoot, options, policy = createDoctorPolicy(options)) {
489
- report.distribution = DISTRIBUTION, checkCliConfig(report), checkHostResolution(report), await checkExternalAuth(report, {
711
+ report.distribution = DISTRIBUTION, await checkExternalAuth(report, {
490
712
  required: policy.authMissingStatus === "fail",
491
713
  useNetwork: !!options.network
492
714
  });
@@ -494,41 +716,40 @@ async function checkDistribution(report, _projectRoot, options, policy = createD
494
716
  var DISTRIBUTION, init_doctorChecks = __esm({
495
717
  "src/distributions/external/doctorChecks.ts"() {
496
718
  "use strict";
719
+ init_user();
497
720
  init_manager();
498
721
  init_policy();
499
722
  init_report();
500
723
  init_authManager();
501
- init_hosts();
502
- init_trackerApiRequest();
503
724
  DISTRIBUTION = "external";
504
725
  }
505
726
  });
506
727
 
507
728
  // src/distribution/doctorChecks.ts
508
- var impl2, checkDistribution2, init_doctorChecks2 = __esm({
729
+ var impl4, checkDistribution2, init_doctorChecks2 = __esm({
509
730
  "src/distribution/doctorChecks.ts"() {
510
731
  "use strict";
511
732
  init_flag();
512
- impl2 = (init_doctorChecks(), __toCommonJS(doctorChecks_exports)), { checkDistribution: checkDistribution2 } = impl2;
733
+ impl4 = (init_doctorChecks(), __toCommonJS(doctorChecks_exports)), { checkDistribution: checkDistribution2 } = impl4;
513
734
  }
514
735
  });
515
736
 
516
737
  // src/core/doctor/distChecks.ts
517
738
  function resolveDistEntrypoint(distDir, entrypoint) {
518
- if (import_path2.default.isAbsolute(entrypoint))
739
+ if (import_path3.default.isAbsolute(entrypoint))
519
740
  return {
520
741
  error: `${entrypoint} is absolute`
521
742
  };
522
- let filePath = import_path2.default.resolve(distDir, import_path2.default.normalize(entrypoint)), relative = import_path2.default.relative(distDir, filePath);
523
- return relative.startsWith("..") || import_path2.default.isAbsolute(relative) ? {
743
+ let filePath = import_path3.default.resolve(distDir, import_path3.default.normalize(entrypoint)), relative = import_path3.default.relative(distDir, filePath);
744
+ return relative.startsWith("..") || import_path3.default.isAbsolute(relative) ? {
524
745
  error: `${entrypoint} escapes dist`
525
746
  } : {
526
747
  filePath
527
748
  };
528
749
  }
529
750
  async function checkDist(report, projectRoot, entries, policy) {
530
- let distDir = import_path2.default.join(projectRoot, "dist");
531
- if (!import_fs2.default.existsSync(distDir)) {
751
+ let distDir = import_path3.default.join(projectRoot, "dist");
752
+ if (!import_fs3.default.existsSync(distDir)) {
532
753
  addCheck(report, {
533
754
  id: "dist.exists",
534
755
  title: "dist directory",
@@ -538,7 +759,7 @@ async function checkDist(report, projectRoot, entries, policy) {
538
759
  });
539
760
  return;
540
761
  }
541
- if (!import_fs2.default.statSync(distDir).isDirectory()) {
762
+ if (!import_fs3.default.statSync(distDir).isDirectory()) {
542
763
  addCheck(report, {
543
764
  id: "dist.exists",
544
765
  title: "dist directory",
@@ -573,7 +794,7 @@ async function checkDist(report, projectRoot, entries, policy) {
573
794
  );
574
795
  continue;
575
796
  }
576
- (!import_fs2.default.existsSync(resolved.filePath) || !import_fs2.default.statSync(resolved.filePath).isFile()) && missingEntrypoints.push(entrypoint);
797
+ (!import_fs3.default.existsSync(resolved.filePath) || !import_fs3.default.statSync(resolved.filePath).isFile()) && missingEntrypoints.push(entrypoint);
577
798
  }
578
799
  invalidEntrypoints.length > 0 ? addCheck(report, {
579
800
  id: "dist.entrypoints.valid",
@@ -597,10 +818,10 @@ async function checkDist(report, projectRoot, entries, policy) {
597
818
  message: "All manifest entrypoints exist in dist."
598
819
  });
599
820
  }
600
- var import_fs2, import_path2, import_tinyglobby, init_distChecks = __esm({
821
+ var import_fs3, import_path3, import_tinyglobby, init_distChecks = __esm({
601
822
  "src/core/doctor/distChecks.ts"() {
602
823
  "use strict";
603
- import_fs2 = __toESM(require("fs")), import_path2 = __toESM(require("path")), import_tinyglobby = require("tinyglobby");
824
+ import_fs3 = __toESM(require("fs")), import_path3 = __toESM(require("path")), import_tinyglobby = require("tinyglobby");
604
825
  init_report();
605
826
  }
606
827
  });
@@ -611,6 +832,7 @@ var TRACKER_SLOTS, init_slots = __esm({
611
832
  "use strict";
612
833
  TRACKER_SLOTS = [
613
834
  "issue.action",
835
+ "drawer.issue.action",
614
836
  "issue.block",
615
837
  "issue.tab",
616
838
  "issue.comment.action",
@@ -647,7 +869,7 @@ var init_src = __esm({
647
869
  });
648
870
 
649
871
  // src/core/manifest/constants.ts
650
- var DATA_PERMISSIONS, TOP_DATA_PERMISSIONS, SERVICES, TEMPLATES, CLI_ONLY_TRACKER_SLOTS, TRACKER_SERVICE_SLOTS, MESSENGER_SERVICE_SLOTS, SERVICE_SLOTS, TEMPLATE_SLOTS, TEMPLATE_SERVICE, init_constants = __esm({
872
+ var DATA_PERMISSIONS, TOP_DATA_PERMISSIONS, SERVICES, TEMPLATES, CLI_ONLY_TRACKER_SLOTS, TRACKER_SERVICE_SLOTS, MESSENGER_SERVICE_SLOTS, SERVICE_SLOTS, TEMPLATE_SLOTS, TEMPLATE_SERVICE, init_constants2 = __esm({
651
873
  "src/core/manifest/constants.ts"() {
652
874
  "use strict";
653
875
  init_src();
@@ -752,7 +974,7 @@ var DATA_PERMISSIONS, TOP_DATA_PERMISSIONS, SERVICES, TEMPLATES, CLI_ONLY_TRACKE
752
974
  "user-card-calendar"
753
975
  ], CLI_ONLY_TRACKER_SLOTS = ["dock"], TRACKER_SERVICE_SLOTS = [...TRACKER_SLOTS, ...CLI_ONLY_TRACKER_SLOTS], MESSENGER_SERVICE_SLOTS = ["user.card.info"], SERVICE_SLOTS = [...TRACKER_SERVICE_SLOTS, ...MESSENGER_SERVICE_SLOTS], TEMPLATE_SLOTS = {
754
976
  default: [],
755
- "issue.action": ["issue.action"],
977
+ "issue.action": ["issue.action", "drawer.issue.action"],
756
978
  "issue.block": ["issue.block"],
757
979
  "issue.tab": ["issue.tab"],
758
980
  "issue.comment.action": ["issue.comment.action"],
@@ -821,11 +1043,11 @@ var permissionsSchemaExtensions, init_manifestPermissionsSchema = __esm({
821
1043
  });
822
1044
 
823
1045
  // src/distribution/manifestPermissionsSchema.ts
824
- var impl3, permissionsSchemaExtensions2, init_manifestPermissionsSchema2 = __esm({
1046
+ var impl5, permissionsSchemaExtensions2, init_manifestPermissionsSchema2 = __esm({
825
1047
  "src/distribution/manifestPermissionsSchema.ts"() {
826
1048
  "use strict";
827
1049
  init_flag();
828
- impl3 = (init_manifestPermissionsSchema(), __toCommonJS(manifestPermissionsSchema_exports)), { permissionsSchemaExtensions: permissionsSchemaExtensions2 } = impl3;
1050
+ impl5 = (init_manifestPermissionsSchema(), __toCommonJS(manifestPermissionsSchema_exports)), { permissionsSchemaExtensions: permissionsSchemaExtensions2 } = impl5;
829
1051
  }
830
1052
  });
831
1053
 
@@ -857,14 +1079,14 @@ var priorityOrder, errorMessages, getPriority, formatValidationErrors, init_form
857
1079
  }, formatValidationErrors = (errors) => {
858
1080
  let errorsByPath = {};
859
1081
  for (let error2 of errors) {
860
- let path24 = error2.instancePath || "root";
861
- errorsByPath[path24] || (errorsByPath[path24] = []), errorsByPath[path24].push(error2);
1082
+ let path26 = error2.instancePath || "root";
1083
+ errorsByPath[path26] || (errorsByPath[path26] = []), errorsByPath[path26].push(error2);
862
1084
  }
863
- return Object.entries(errorsByPath).map(([path24, pathErrors]) => {
1085
+ return Object.entries(errorsByPath).map(([path26, pathErrors]) => {
864
1086
  let error2 = [...pathErrors].sort(
865
1087
  (a, b) => getPriority(a.keyword) - getPriority(b.keyword)
866
1088
  )[0], formatter = errorMessages[error2.keyword], message = formatter ? formatter(error2.params) : error2.message;
867
- return ` - ${path24}: ${message}`;
1089
+ return ` - ${path26}: ${message}`;
868
1090
  }).join(`
869
1091
  `);
870
1092
  };
@@ -891,6 +1113,12 @@ var manifest_schema_default, init_manifest_schema = __esm({
891
1113
  $schema: {
892
1114
  type: "string"
893
1115
  },
1116
+ docsUrl: {
1117
+ type: "string",
1118
+ description: "URL to the documentation for the plugin",
1119
+ maxLength: 1e3,
1120
+ minLength: 1
1121
+ },
894
1122
  id: {
895
1123
  type: "string",
896
1124
  description: "Unique identifier for the plugin ()",
@@ -1003,6 +1231,16 @@ var manifest_schema_default, init_manifest_schema = __esm({
1003
1231
  },
1004
1232
  minItems: 1
1005
1233
  },
1234
+ categories: {
1235
+ type: "array",
1236
+ description: "Categories for plugin discovery in the marketplace",
1237
+ items: {
1238
+ type: "string",
1239
+ minLength: 1,
1240
+ maxLength: 50
1241
+ },
1242
+ uniqueItems: !0
1243
+ },
1006
1244
  homepage: {
1007
1245
  type: "string",
1008
1246
  description: "Homepage URL for the plugin (http or https)",
@@ -1177,6 +1415,14 @@ var manifest_schema_default, init_manifest_schema = __esm({
1177
1415
  $ref: "#/definitions/SlotConfig"
1178
1416
  }
1179
1417
  },
1418
+ "drawer.issue.action": {
1419
+ type: "array",
1420
+ description: "Drawer Issue Action slot configurations",
1421
+ minItems: 1,
1422
+ items: {
1423
+ $ref: "#/definitions/SlotConfig"
1424
+ }
1425
+ },
1180
1426
  "issue.block": {
1181
1427
  type: "array",
1182
1428
  description: "Issue Block slot configurations",
@@ -1578,10 +1824,10 @@ var manifest_schema_default, init_manifest_schema = __esm({
1578
1824
  });
1579
1825
 
1580
1826
  // src/core/manifest/manifestManager.ts
1581
- var import_fs3, import_promises, import_ajv, import_ajv_formats, validator, defaultManifestPath, parseManifest, loadRaw, load, validate, save, update, manifestManager, init_manifestManager = __esm({
1827
+ var import_fs4, import_promises, import_ajv, import_ajv_formats, validator, defaultManifestPath, parseManifest, loadRaw, load, validate, save, update, manifestManager, init_manifestManager = __esm({
1582
1828
  "src/core/manifest/manifestManager.ts"() {
1583
1829
  "use strict";
1584
- import_fs3 = require("fs"), import_promises = require("fs/promises"), import_ajv = __toESM(require("ajv")), import_ajv_formats = __toESM(require("ajv-formats"));
1830
+ import_fs4 = require("fs"), import_promises = require("fs/promises"), import_ajv = __toESM(require("ajv")), import_ajv_formats = __toESM(require("ajv-formats"));
1585
1831
  init_manifestPermissionsSchema2();
1586
1832
  init_formatValidationErrors();
1587
1833
  init_manifest_schema();
@@ -1609,7 +1855,7 @@ var import_fs3, import_promises, import_ajv, import_ajv_formats, validator, defa
1609
1855
  }
1610
1856
  return manifest;
1611
1857
  }, loadRaw = async (manifestPath = defaultManifestPath) => {
1612
- if (!(0, import_fs3.existsSync)(manifestPath))
1858
+ if (!(0, import_fs4.existsSync)(manifestPath))
1613
1859
  throw new Error(`File manifest.json not found at path: ${manifestPath}`);
1614
1860
  try {
1615
1861
  return await (0, import_promises.readFile)(manifestPath, "utf8");
@@ -1665,10 +1911,10 @@ function isNonEmptyString(value) {
1665
1911
  return typeof value == "string" && !!value.trim();
1666
1912
  }
1667
1913
  function isSafeRelativePath(value) {
1668
- if (import_path3.default.isAbsolute(value))
1914
+ if (import_path4.default.isAbsolute(value))
1669
1915
  return !1;
1670
- let normalized = import_path3.default.normalize(value);
1671
- return normalized !== ".." && !normalized.startsWith(`..${import_path3.default.sep}`);
1916
+ let normalized = import_path4.default.normalize(value);
1917
+ return normalized !== ".." && !normalized.startsWith(`..${import_path4.default.sep}`);
1672
1918
  }
1673
1919
  function getManifestEntries(manifest) {
1674
1920
  let result = [];
@@ -1799,11 +2045,11 @@ async function checkManifest(report, manifestPath, policy) {
1799
2045
  };
1800
2046
  }
1801
2047
  }
1802
- var import_path3, init_manifestChecks = __esm({
2048
+ var import_path4, init_manifestChecks = __esm({
1803
2049
  "src/core/doctor/manifestChecks.ts"() {
1804
2050
  "use strict";
1805
- import_path3 = __toESM(require("path"));
1806
- init_constants();
2051
+ import_path4 = __toESM(require("path"));
2052
+ init_constants2();
1807
2053
  init_manifestManager();
1808
2054
  init_helpers();
1809
2055
  init_report();
@@ -1816,8 +2062,8 @@ function getMissingOrInvalidStatus(requiredPath, policy) {
1816
2062
  }
1817
2063
  function checkMarketplaceAssets(report, projectRoot, policy) {
1818
2064
  for (let requiredPath of REQUIRED_PATHS) {
1819
- let fullPath = import_path4.default.join(projectRoot, requiredPath.path), status = getMissingOrInvalidStatus(requiredPath, policy);
1820
- if (!import_fs4.default.existsSync(fullPath)) {
2065
+ let fullPath = import_path5.default.join(projectRoot, requiredPath.path), status = getMissingOrInvalidStatus(requiredPath, policy);
2066
+ if (!import_fs5.default.existsSync(fullPath)) {
1821
2067
  addCheck(report, {
1822
2068
  id: `marketplace.${requiredPath.path}`,
1823
2069
  title: requiredPath.title,
@@ -1827,7 +2073,7 @@ function checkMarketplaceAssets(report, projectRoot, policy) {
1827
2073
  });
1828
2074
  continue;
1829
2075
  }
1830
- let stat = import_fs4.default.statSync(fullPath), validKind = requiredPath.kind === "directory" ? stat.isDirectory() : stat.isFile();
2076
+ let stat = import_fs5.default.statSync(fullPath), validKind = requiredPath.kind === "directory" ? stat.isDirectory() : stat.isFile();
1831
2077
  addCheck(report, {
1832
2078
  id: `marketplace.${requiredPath.path}`,
1833
2079
  title: requiredPath.title,
@@ -1837,10 +2083,10 @@ function checkMarketplaceAssets(report, projectRoot, policy) {
1837
2083
  });
1838
2084
  }
1839
2085
  }
1840
- var import_fs4, import_path4, REQUIRED_PATHS, init_marketplaceChecks = __esm({
2086
+ var import_fs5, import_path5, REQUIRED_PATHS, init_marketplaceChecks = __esm({
1841
2087
  "src/core/doctor/marketplaceChecks.ts"() {
1842
2088
  "use strict";
1843
- import_fs4 = __toESM(require("fs")), import_path4 = __toESM(require("path"));
2089
+ import_fs5 = __toESM(require("fs")), import_path5 = __toESM(require("path"));
1844
2090
  init_report();
1845
2091
  REQUIRED_PATHS = [
1846
2092
  { path: "src", title: "Source directory", kind: "directory" },
@@ -1897,10 +2143,10 @@ function defaultCommandExists(command) {
1897
2143
  return !result.error && result.status === 0;
1898
2144
  }
1899
2145
  function detectFromPackageJson(projectRoot) {
1900
- let packageJsonPath = import_path5.default.join(projectRoot, "package.json");
1901
- if (import_fs5.default.existsSync(packageJsonPath))
2146
+ let packageJsonPath = import_path6.default.join(projectRoot, "package.json");
2147
+ if (import_fs6.default.existsSync(packageJsonPath))
1902
2148
  try {
1903
- let raw = import_fs5.default.readFileSync(packageJsonPath, "utf8"), packageManager = JSON.parse(raw).packageManager;
2149
+ let raw = import_fs6.default.readFileSync(packageJsonPath, "utf8"), packageManager = JSON.parse(raw).packageManager;
1904
2150
  if (typeof packageManager != "string")
1905
2151
  return;
1906
2152
  if (packageManager.startsWith("pnpm@"))
@@ -1912,7 +2158,7 @@ function detectFromPackageJson(projectRoot) {
1912
2158
  }
1913
2159
  }
1914
2160
  function detectPackageManager(projectRoot = process.cwd()) {
1915
- return import_fs5.default.existsSync(import_path5.default.join(projectRoot, "pnpm-lock.yaml")) ? "pnpm" : detectFromPackageJson(projectRoot) || "npm";
2161
+ return import_fs6.default.existsSync(import_path6.default.join(projectRoot, "pnpm-lock.yaml")) ? "pnpm" : detectFromPackageJson(projectRoot) || "npm";
1916
2162
  }
1917
2163
  function resolvePackageManagerExecutable(packageManager, options = {}) {
1918
2164
  let commandExists = options.commandExists || defaultCommandExists;
@@ -1981,10 +2227,10 @@ function runPackageManagerRuntimeCheck(projectRoot, packageManager, executable)
1981
2227
  output: output || null
1982
2228
  };
1983
2229
  }
1984
- var import_child_process, import_fs5, import_path5, PACKAGE_MANAGER_RUNTIME_TIMEOUT_MS, MAX_RUNTIME_OUTPUT_LENGTH, PackageManagerRuntimeError, init_packageManager = __esm({
2230
+ var import_child_process, import_fs6, import_path6, PACKAGE_MANAGER_RUNTIME_TIMEOUT_MS, MAX_RUNTIME_OUTPUT_LENGTH, PackageManagerRuntimeError, init_packageManager = __esm({
1985
2231
  "src/utils/packageManager.ts"() {
1986
2232
  "use strict";
1987
- import_child_process = require("child_process"), import_fs5 = __toESM(require("fs")), import_path5 = __toESM(require("path")), PACKAGE_MANAGER_RUNTIME_TIMEOUT_MS = 15e3, MAX_RUNTIME_OUTPUT_LENGTH = 1e3, PackageManagerRuntimeError = class extends Error {
2233
+ import_child_process = require("child_process"), import_fs6 = __toESM(require("fs")), import_path6 = __toESM(require("path")), PACKAGE_MANAGER_RUNTIME_TIMEOUT_MS = 15e3, MAX_RUNTIME_OUTPUT_LENGTH = 1e3, PackageManagerRuntimeError = class extends Error {
1988
2234
  constructor(check) {
1989
2235
  super(check.message), this.name = "PackageManagerRuntimeError", this.action = check.action, this.check = check;
1990
2236
  }
@@ -1994,14 +2240,14 @@ var import_child_process, import_fs5, import_path5, PACKAGE_MANAGER_RUNTIME_TIME
1994
2240
 
1995
2241
  // src/core/doctor/packageChecks.ts
1996
2242
  function readPackageJson(projectRoot) {
1997
- let packageJsonPath = import_path6.default.join(projectRoot, "package.json");
1998
- if (!import_fs6.default.existsSync(packageJsonPath))
2243
+ let packageJsonPath = import_path7.default.join(projectRoot, "package.json");
2244
+ if (!import_fs7.default.existsSync(packageJsonPath))
1999
2245
  return {
2000
2246
  path: packageJsonPath,
2001
2247
  error: "package.json not found"
2002
2248
  };
2003
2249
  try {
2004
- let raw = import_fs6.default.readFileSync(packageJsonPath, "utf8");
2250
+ let raw = import_fs7.default.readFileSync(packageJsonPath, "utf8");
2005
2251
  return {
2006
2252
  path: packageJsonPath,
2007
2253
  packageJson: JSON.parse(raw)
@@ -2188,10 +2434,10 @@ function checkPackageManager(report, projectRoot) {
2188
2434
  });
2189
2435
  }
2190
2436
  }
2191
- var import_fs6, import_path6, CLI_PACKAGE_MANAGER, COMMON_SDK_PACKAGES, GENERIC_SDK_PACKAGES, init_packageChecks = __esm({
2437
+ var import_fs7, import_path7, CLI_PACKAGE_MANAGER, COMMON_SDK_PACKAGES, GENERIC_SDK_PACKAGES, init_packageChecks = __esm({
2192
2438
  "src/core/doctor/packageChecks.ts"() {
2193
2439
  "use strict";
2194
- import_fs6 = __toESM(require("fs")), import_path6 = __toESM(require("path"));
2440
+ import_fs7 = __toESM(require("fs")), import_path7 = __toESM(require("path"));
2195
2441
  init_packageManager();
2196
2442
  init_helpers();
2197
2443
  init_report();
@@ -2208,368 +2454,92 @@ var import_fs6, import_path6, CLI_PACKAGE_MANAGER, COMMON_SDK_PACKAGES, GENERIC_
2208
2454
 
2209
2455
  // src/utils/project.ts
2210
2456
  function resolveProjectRoot(startDir = process.cwd()) {
2211
- let current = import_path7.default.resolve(startDir);
2457
+ let current = import_path8.default.resolve(startDir);
2212
2458
  for (; ; ) {
2213
- if (import_fs7.default.existsSync(import_path7.default.join(current, MANIFEST_FILE)))
2214
- return current;
2215
- let parent = import_path7.default.dirname(current);
2216
- if (parent === current)
2217
- throw new Error(
2218
- `Could not find ${MANIFEST_FILE}. Run this command inside a plugin project.`
2219
- );
2220
- current = parent;
2221
- }
2222
- }
2223
- function getManifestPath(projectRoot = process.cwd()) {
2224
- return import_path7.default.join(resolveProjectRoot(projectRoot), MANIFEST_FILE);
2225
- }
2226
- var import_fs7, import_path7, MANIFEST_FILE, init_project = __esm({
2227
- "src/utils/project.ts"() {
2228
- "use strict";
2229
- import_fs7 = __toESM(require("fs")), import_path7 = __toESM(require("path")), MANIFEST_FILE = "manifest.json";
2230
- }
2231
- });
2232
-
2233
- // src/core/doctor/projectChecks.ts
2234
- function checkProjectRoot(report) {
2235
- try {
2236
- let projectRoot = resolveProjectRoot();
2237
- return report.projectRoot = projectRoot, report.manifestPath = getManifestPath(projectRoot), addCheck(report, {
2238
- id: "project-root.resolved",
2239
- title: "Project root",
2240
- message: `Found plugin project root at ${projectRoot}.`
2241
- }), projectRoot;
2242
- } catch (error2) {
2243
- addCheck(report, {
2244
- id: "project-root.resolved",
2245
- title: "Project root",
2246
- status: "fail",
2247
- message: getErrorMessage(error2),
2248
- action: "Run doctor inside a generated plugin project."
2249
- });
2250
- return;
2251
- }
2252
- }
2253
- var init_projectChecks = __esm({
2254
- "src/core/doctor/projectChecks.ts"() {
2255
- "use strict";
2256
- init_project();
2257
- init_helpers();
2258
- init_report();
2259
- }
2260
- });
2261
-
2262
- // src/core/doctor/checks.ts
2263
- async function runDoctorChecks(options) {
2264
- let report = createDoctorReport(), policy = createDoctorPolicy(options);
2265
- report.mode = policy.mode, checkNodeVersion(report);
2266
- let projectRoot = checkProjectRoot(report);
2267
- if (!projectRoot)
2268
- return await checkDistribution2(report, void 0, options, policy), report;
2269
- let { manifest, entries } = await checkManifest(report, report.manifestPath, policy);
2270
- return checkPackageJson(report, projectRoot) && checkPackageManager(report, projectRoot), manifest && await checkDist(report, projectRoot, entries, policy), checkMarketplaceAssets(report, projectRoot, policy), await checkDistribution2(report, projectRoot, options, policy), report;
2271
- }
2272
- var init_checks = __esm({
2273
- "src/core/doctor/checks.ts"() {
2274
- "use strict";
2275
- init_doctorChecks2();
2276
- init_distChecks();
2277
- init_manifestChecks();
2278
- init_marketplaceChecks();
2279
- init_nodeChecks();
2280
- init_packageChecks();
2281
- init_policy();
2282
- init_projectChecks();
2283
- init_report();
2284
- }
2285
- });
2286
-
2287
- // src/commands/doctor/index.ts
2288
- async function doctor(options = {}) {
2289
- let report = await runDoctorChecks(options);
2290
- await finishDoctor(report, options);
2291
- }
2292
- var init_doctor = __esm({
2293
- "src/commands/doctor/index.ts"() {
2294
- "use strict";
2295
- init_checks();
2296
- init_report();
2297
- }
2298
- });
2299
-
2300
- // src/distributions/external/auth.ts
2301
- var auth_exports = {};
2302
- __export(auth_exports, {
2303
- getAuthHeader: () => getAuthHeader,
2304
- getPlatformHeaders: () => getPlatformHeaders
2305
- });
2306
- function getAuthHeader() {
2307
- let token = externalAuthManager.token;
2308
- return token ? `OAuth ${token}` : null;
2309
- }
2310
- function getPlatformHeaders() {
2311
- let orgId = readConfig()?.api?.platformOrgId;
2312
- return orgId ? { "X-Org-ID": orgId } : {};
2313
- }
2314
- var init_auth = __esm({
2315
- "src/distributions/external/auth.ts"() {
2316
- "use strict";
2317
- init_manager();
2318
- init_authManager();
2319
- }
2320
- });
2321
-
2322
- // src/distribution/auth.ts
2323
- var impl4, getAuthHeader2, getPlatformHeaders2, init_auth2 = __esm({
2324
- "src/distribution/auth.ts"() {
2325
- "use strict";
2326
- init_flag();
2327
- impl4 = (init_auth(), __toCommonJS(auth_exports)), { getAuthHeader: getAuthHeader2, getPlatformHeaders: getPlatformHeaders2 } = impl4;
2328
- }
2329
- });
2330
-
2331
- // src/utils/verbose.ts
2332
- function setVerboseEnabled(value) {
2333
- verboseEnabled = value;
2334
- }
2335
- function isVerboseEnabled() {
2336
- return verboseEnabled;
2337
- }
2338
- function writeVerboseArtifact(relativePath, content) {
2339
- let targetPath = import_path8.default.resolve(".yaweavix-debug", relativePath);
2340
- return import_fs8.default.mkdirSync(import_path8.default.dirname(targetPath), { recursive: !0 }), import_fs8.default.writeFileSync(targetPath, content), targetPath;
2341
- }
2342
- var import_fs8, import_path8, verboseEnabled, init_verbose = __esm({
2343
- "src/utils/verbose.ts"() {
2344
- "use strict";
2345
- import_fs8 = __toESM(require("fs")), import_path8 = __toESM(require("path")), verboseEnabled = !1;
2346
- }
2347
- });
2348
-
2349
- // src/utils/logger.ts
2350
- function success(message) {
2351
- console.info(import_picocolors.default.green(`\u2705 ${message}`)), newLine();
2352
- }
2353
- function error(messageOrErr, err) {
2354
- let message = messageOrErr instanceof Error ? messageOrErr.message : messageOrErr;
2355
- console.error(import_picocolors.default.red(`\u274C ${message}`)), err instanceof Error && console.error(import_picocolors.default.red(err.message)), newLine();
2356
- }
2357
- function warning(message) {
2358
- console.warn(import_picocolors.default.yellow(`\u26A0\uFE0F ${message}`)), newLine();
2359
- }
2360
- function info(message) {
2361
- console.info(message), newLine();
2362
- }
2363
- function verbose(message) {
2364
- isVerboseEnabled() && (console.info(import_picocolors.default.dim(message)), newLine());
2365
- }
2366
- function suggest(command) {
2367
- console.info(`Run: ${command}`), newLine();
2368
- }
2369
- function newLine(count = 1) {
2370
- console.info(`
2371
- `.repeat(count - 1));
2372
- }
2373
- function separator(char = "\u2500", length = 60) {
2374
- console.info(import_picocolors.default.dim(char.repeat(length))), newLine();
2375
- }
2376
- function commands(title, data) {
2377
- newLine(), title && (console.info(import_picocolors.default.bold(import_picocolors.default.cyan(`${title}:`))), newLine()), data.forEach((cmd) => {
2378
- console.info(import_picocolors.default.dim(" $ ") + import_picocolors.default.white(cmd));
2379
- }), newLine();
2380
- }
2381
- var import_picocolors, logger, logger_default, init_logger = __esm({
2382
- "src/utils/logger.ts"() {
2383
- "use strict";
2384
- import_picocolors = __toESM(require("picocolors"));
2385
- init_verbose();
2386
- logger = {
2387
- success,
2388
- error,
2389
- warning,
2390
- info,
2391
- verbose,
2392
- suggest,
2393
- newLine,
2394
- separator,
2395
- commands
2396
- }, logger_default = logger;
2397
- }
2398
- });
2399
-
2400
- // src/distribution/hosts.ts
2401
- var impl5, getS3Endpoint2, getMdsEndpoint2, getS3Region2, getBuckets2, getPluginDownloadBase2, getPlatformBaseUrl2, getPlatformApiPrefix2, getTrackerBaseUrl2, getOAuthTokenUrl2, getUpdateCheckInfo2, init_hosts2 = __esm({
2402
- "src/distribution/hosts.ts"() {
2403
- "use strict";
2404
- init_flag();
2405
- impl5 = (init_hosts(), __toCommonJS(hosts_exports)), {
2406
- getS3Endpoint: getS3Endpoint2,
2407
- getMdsEndpoint: getMdsEndpoint2,
2408
- getS3Region: getS3Region2,
2409
- getBuckets: getBuckets2,
2410
- getPluginDownloadBase: getPluginDownloadBase2,
2411
- getPlatformBaseUrl: getPlatformBaseUrl2,
2412
- getPlatformApiPrefix: getPlatformApiPrefix2,
2413
- getTrackerBaseUrl: getTrackerBaseUrl2,
2414
- getOAuthTokenUrl: getOAuthTokenUrl2,
2415
- getUpdateCheckInfo: getUpdateCheckInfo2
2416
- } = impl5;
2417
- }
2418
- });
2419
-
2420
- // src/api/constants.ts
2421
- var init_constants2 = __esm({
2422
- "src/api/constants.ts"() {
2423
- "use strict";
2424
- init_hosts2();
2425
- init_hosts2();
2426
- }
2427
- });
2428
-
2429
- // src/api/requestDebug.ts
2430
- function redactHeaders(headers) {
2431
- let result = {};
2432
- for (let [key, value] of Object.entries(headers))
2433
- if (key.toLowerCase() === "authorization") {
2434
- let [scheme] = value.split(" ");
2435
- result[key] = scheme ? `${scheme} ${REDACTED}` : REDACTED;
2436
- } else
2437
- result[key] = value;
2438
- return result;
2439
- }
2440
- function formatDebugBody(body, formData) {
2441
- if (formData) {
2442
- let size = "";
2443
- try {
2444
- let length = formData.getLengthSync?.();
2445
- typeof length == "number" && (size = `, ~${length} bytes`);
2446
- } catch {
2447
- }
2448
- return `[multipart/form-data${size}] (binary body, e.g. plugin archive \u2014 not dumped)`;
2459
+ if (import_fs8.default.existsSync(import_path8.default.join(current, MANIFEST_FILE)))
2460
+ return current;
2461
+ let parent = import_path8.default.dirname(current);
2462
+ if (parent === current)
2463
+ throw new Error(
2464
+ `Could not find ${MANIFEST_FILE}. Run this command inside a plugin project.`
2465
+ );
2466
+ current = parent;
2449
2467
  }
2450
- return typeof body == "string" ? body : "(none)";
2451
2468
  }
2452
- function buildFailureDebug(params) {
2453
- let { method, url, status, headers, body, formData } = params;
2454
- return [
2455
- "Platform API request failed \u2014 debug info (Authorization redacted):",
2456
- ` method: ${method}`,
2457
- ` url: ${url}`,
2458
- ` status: ${status ?? "(no HTTP response \u2014 network/transport error)"}`,
2459
- ` headers: ${JSON.stringify(redactHeaders(headers), null, 2)}`,
2460
- ` body: ${formatDebugBody(body, formData)}`
2461
- ].join(`
2462
- `);
2469
+ function getManifestPath(projectRoot = process.cwd()) {
2470
+ return import_path8.default.join(resolveProjectRoot(projectRoot), MANIFEST_FILE);
2463
2471
  }
2464
- var REDACTED, init_requestDebug = __esm({
2465
- "src/api/requestDebug.ts"() {
2472
+ var import_fs8, import_path8, MANIFEST_FILE, init_project = __esm({
2473
+ "src/utils/project.ts"() {
2466
2474
  "use strict";
2467
- REDACTED = "****redacted****";
2475
+ import_fs8 = __toESM(require("fs")), import_path8 = __toESM(require("path")), MANIFEST_FILE = "manifest.json";
2468
2476
  }
2469
2477
  });
2470
2478
 
2471
- // src/api/platformApiRequest.ts
2472
- function buildRequestHeaders(headers, formData) {
2473
- let authHeader = getAuthHeader2();
2474
- if (!authHeader)
2475
- throw new Error(`Not authenticated. Run "${CLI_NAME2} login" first.`);
2476
- let requestHeaders = {
2477
- Accept: "*/*",
2478
- Authorization: authHeader,
2479
- ...getPlatformHeaders2(),
2480
- ...headers
2481
- };
2482
- return formData || (requestHeaders["Content-Type"] = "application/json"), requestHeaders;
2483
- }
2484
- function buildRequestBody(method, body, formData) {
2485
- if (formData) {
2486
- let formHeaders = formData.getHeaders?.();
2487
- return {
2488
- body: formData,
2489
- headers: formHeaders || {}
2490
- };
2479
+ // src/core/doctor/projectChecks.ts
2480
+ function checkProjectRoot(report) {
2481
+ try {
2482
+ let projectRoot = resolveProjectRoot();
2483
+ return report.projectRoot = projectRoot, report.manifestPath = getManifestPath(projectRoot), addCheck(report, {
2484
+ id: "project-root.resolved",
2485
+ title: "Project root",
2486
+ message: `Found plugin project root at ${projectRoot}.`
2487
+ }), projectRoot;
2488
+ } catch (error2) {
2489
+ addCheck(report, {
2490
+ id: "project-root.resolved",
2491
+ title: "Project root",
2492
+ status: "fail",
2493
+ message: getErrorMessage(error2),
2494
+ action: "Run doctor inside a generated plugin project."
2495
+ });
2496
+ return;
2491
2497
  }
2492
- return body && method !== "GET" ? { body: JSON.stringify(body) } : {};
2493
- }
2494
- function buildQueryString2(queryParams) {
2495
- if (!queryParams || Object.keys(queryParams).length === 0)
2496
- return "";
2497
- let params = new URLSearchParams();
2498
- return Object.entries(queryParams).forEach(([key, value]) => {
2499
- params.append(key, String(value));
2500
- }), `?${params.toString()}`;
2501
- }
2502
- async function parseResponse2(response) {
2503
- return response.status === 204 || response.headers.get("content-length") === "0" ? void 0 : response.headers.get("content-type")?.includes("application/json") ? await response.json() : await response.text();
2504
2498
  }
2505
- async function platformApiRequest(endpoint, options = {}) {
2506
- let { method = "GET", body, headers = {}, formData, queryParams } = options, requestHeaders = buildRequestHeaders(headers, formData), { body: requestBody, headers: additionalHeaders } = buildRequestBody(
2507
- method,
2508
- body,
2509
- formData
2510
- ), requestOptions = {
2511
- method,
2512
- headers: { ...requestHeaders, ...additionalHeaders },
2513
- body: requestBody
2514
- }, queryString = buildQueryString2(queryParams), url = `${getPlatformBaseUrl2()}${getPlatformApiPrefix2()}${endpoint}${queryString}`, controller = new AbortController(), timeout = setTimeout(() => controller.abort(), PLATFORM_API_TIMEOUT_MS), responseStatus;
2515
- if (isVerboseEnabled() && (logger_default.info(
2516
- `[platform-api-debug] Request: method=${method} url=${url} hasBody=${!!body} hasFormData=${!!formData} timeoutMs=${PLATFORM_API_TIMEOUT_MS}`
2517
- ), body !== void 0 && logger_default.info(`[platform-api-debug] Request body: ${JSON.stringify(body)}`), formData)) {
2518
- let debugPath = writeVerboseArtifact(
2519
- "requests/latest-form-data.txt",
2520
- `method=${method}
2521
- url=${url}
2522
- headers=${JSON.stringify({ ...requestHeaders, ...additionalHeaders }, null, 2)}
2523
- formData=present
2524
- `
2525
- );
2526
- logger_default.info(`[platform-api-debug] Saved form-data request metadata to ${debugPath}`);
2499
+ var init_projectChecks = __esm({
2500
+ "src/core/doctor/projectChecks.ts"() {
2501
+ "use strict";
2502
+ init_project();
2503
+ init_helpers();
2504
+ init_report();
2527
2505
  }
2528
- try {
2529
- let response = await (0, import_node_fetch2.default)(url, {
2530
- ...requestOptions,
2531
- signal: controller.signal
2532
- });
2533
- if (responseStatus = response.status, isVerboseEnabled() && logger_default.info(
2534
- `[platform-api-debug] Response: method=${method} url=${url} status=${response.status} contentType=${response.headers.get("content-type") ?? "n/a"}`
2535
- ), !response.ok) {
2536
- let errorText = await response.text(), errorMessage = errorText;
2537
- try {
2538
- let errorJson = JSON.parse(errorText);
2539
- errorJson.message && (errorMessage = errorJson.message);
2540
- } catch {
2541
- }
2542
- throw new Error(`HTTP ${response.status} ${response.statusText}: ${errorMessage}`);
2543
- }
2544
- return parseResponse2(response);
2545
- } catch (error2) {
2546
- throw logger_default.error(
2547
- buildFailureDebug({
2548
- method,
2549
- url,
2550
- status: responseStatus,
2551
- headers: requestOptions.headers,
2552
- body: requestBody,
2553
- formData
2554
- })
2555
- ), error2 instanceof Error && error2.name === "AbortError" ? new Error(
2556
- `Platform API request timed out after ${PLATFORM_API_TIMEOUT_MS}ms: ${method} ${url}`
2557
- ) : error2;
2558
- } finally {
2559
- clearTimeout(timeout);
2506
+ });
2507
+
2508
+ // src/core/doctor/checks.ts
2509
+ async function runDoctorChecks(options) {
2510
+ let report = createDoctorReport(), policy = createDoctorPolicy(options);
2511
+ report.mode = policy.mode, checkNodeVersion(report);
2512
+ let projectRoot = checkProjectRoot(report);
2513
+ if (!projectRoot)
2514
+ return await checkDistribution2(report, void 0, options, policy), report;
2515
+ let { manifest, entries } = await checkManifest(report, report.manifestPath, policy);
2516
+ return checkPackageJson(report, projectRoot) && checkPackageManager(report, projectRoot), manifest && await checkDist(report, projectRoot, entries, policy), checkMarketplaceAssets(report, projectRoot, policy), await checkDistribution2(report, projectRoot, options, policy), report;
2517
+ }
2518
+ var init_checks = __esm({
2519
+ "src/core/doctor/checks.ts"() {
2520
+ "use strict";
2521
+ init_doctorChecks2();
2522
+ init_distChecks();
2523
+ init_manifestChecks();
2524
+ init_marketplaceChecks();
2525
+ init_nodeChecks();
2526
+ init_packageChecks();
2527
+ init_policy();
2528
+ init_projectChecks();
2529
+ init_report();
2560
2530
  }
2531
+ });
2532
+
2533
+ // src/commands/doctor/index.ts
2534
+ async function doctor(options = {}) {
2535
+ let report = await runDoctorChecks(options);
2536
+ await finishDoctor(report, options);
2561
2537
  }
2562
- var import_node_fetch2, PLATFORM_API_TIMEOUT_MS, init_platformApiRequest = __esm({
2563
- "src/api/platformApiRequest.ts"() {
2538
+ var init_doctor = __esm({
2539
+ "src/commands/doctor/index.ts"() {
2564
2540
  "use strict";
2565
- import_node_fetch2 = __toESM(require("node-fetch"));
2566
- init_auth2();
2567
- init_meta2();
2568
- init_logger();
2569
- init_verbose();
2570
- init_constants2();
2571
- init_requestDebug();
2572
- PLATFORM_API_TIMEOUT_MS = Number(process.env.TRACKER_CLI_PLATFORM_TIMEOUT_MS || 3e4);
2541
+ init_checks();
2542
+ init_report();
2573
2543
  }
2574
2544
  });
2575
2545
 
@@ -2633,10 +2603,14 @@ async function checkSlugAvailability(slug) {
2633
2603
  method: "GET"
2634
2604
  });
2635
2605
  }
2606
+ async function getPluginCategories() {
2607
+ return mockedCategories;
2608
+ }
2636
2609
  var import_form_data, init_platform = __esm({
2637
2610
  "src/api/platform.ts"() {
2638
2611
  "use strict";
2639
2612
  import_form_data = __toESM(require("form-data"));
2613
+ init_constants();
2640
2614
  init_platformApiRequest();
2641
2615
  }
2642
2616
  });
@@ -2661,13 +2635,6 @@ var init_getPluginId = __esm({
2661
2635
  }
2662
2636
  });
2663
2637
 
2664
- // src/api/utils.ts
2665
- var init_utils = __esm({
2666
- "src/api/utils.ts"() {
2667
- "use strict";
2668
- }
2669
- });
2670
-
2671
2638
  // src/utils/pluginDisplay.ts
2672
2639
  function showPluginInfo(data) {
2673
2640
  printHeader("\u{1F4E6} Plugin"), logger_default.newLine(), printPluginId(data.id), printField("Slug", import_picocolors2.default.magenta(data.slug)), printField("Name", import_picocolors2.default.white(data.name)), printField("Status", getStatusBadgeByLabel(data.status.toUpperCase())), data.moderationTicketKey && printField("Moderation", import_picocolors2.default.cyan(data.moderationTicketKey)), data.createdAt && printCreated(data.createdAt), data.updatedAt && printUpdated(data.updatedAt);
@@ -2699,7 +2666,6 @@ var import_picocolors2, printHeader, printSuccessHeader, getStatusBadgeByLabel,
2699
2666
  "src/utils/pluginDisplay.ts"() {
2700
2667
  "use strict";
2701
2668
  import_picocolors2 = __toESM(require("picocolors"));
2702
- init_utils();
2703
2669
  init_logger();
2704
2670
  printHeader = (title) => {
2705
2671
  console.info(import_picocolors2.default.bold(import_picocolors2.default.white(title)));
@@ -2726,8 +2692,25 @@ var import_picocolors2, printHeader, printSuccessHeader, getStatusBadgeByLabel,
2726
2692
  }
2727
2693
  });
2728
2694
 
2695
+ // src/commands/platformAuth.ts
2696
+ function applyPlatformAuthOptions(options = {}) {
2697
+ setPlatformIamToken(options.iamToken);
2698
+ }
2699
+ var import_commander, iamTokenOption, init_platformAuth = __esm({
2700
+ "src/commands/platformAuth.ts"() {
2701
+ "use strict";
2702
+ import_commander = require("commander");
2703
+ init_platformApiRequest();
2704
+ iamTokenOption = new import_commander.Option(
2705
+ "--iam-token <token>",
2706
+ "use IAM token for Platform API requests instead of OAuth"
2707
+ );
2708
+ }
2709
+ });
2710
+
2729
2711
  // src/commands/info/platform.ts
2730
- async function infoPlatform(pluginId) {
2712
+ async function infoPlatform(pluginId, options = {}) {
2713
+ applyPlatformAuthOptions(options);
2731
2714
  let actualPluginId = await getPluginId(pluginId);
2732
2715
  logger_default.info(`\u23F3 Fetching plugin info for ID: ${actualPluginId}...`);
2733
2716
  try {
@@ -2744,12 +2727,13 @@ var init_platform2 = __esm({
2744
2727
  init_getPluginId();
2745
2728
  init_logger();
2746
2729
  init_pluginDisplay();
2730
+ init_platformAuth();
2747
2731
  }
2748
2732
  });
2749
2733
 
2750
2734
  // src/commands/list/platform.ts
2751
- async function listPlatform() {
2752
- logger_default.info("\u23F3 Fetching my plugins...");
2735
+ async function listPlatform(options = {}) {
2736
+ applyPlatformAuthOptions(options), logger_default.info("\u23F3 Fetching my plugins...");
2753
2737
  try {
2754
2738
  let plugins = await getMyPlugins();
2755
2739
  showPluginList(plugins);
@@ -2763,14 +2747,15 @@ var init_platform3 = __esm({
2763
2747
  init_platform();
2764
2748
  init_logger();
2765
2749
  init_pluginDisplay();
2750
+ init_platformAuth();
2766
2751
  }
2767
2752
  });
2768
2753
 
2769
2754
  // src/commands/submit/options.ts
2770
- var import_commander, skipChecksOption, init_options = __esm({
2755
+ var import_commander2, skipChecksOption, init_options = __esm({
2771
2756
  "src/commands/submit/options.ts"() {
2772
2757
  "use strict";
2773
- import_commander = require("commander"), skipChecksOption = new import_commander.Option(
2758
+ import_commander2 = require("commander"), skipChecksOption = new import_commander2.Option(
2774
2759
  "--skip-checks",
2775
2760
  "skip pre-submit validation (manifest, assets, lint, typecheck, tests, audit)"
2776
2761
  );
@@ -2778,6 +2763,22 @@ var import_commander, skipChecksOption, init_options = __esm({
2778
2763
  });
2779
2764
 
2780
2765
  // src/utils/marketplace.ts
2766
+ function validateDocs() {
2767
+ let docsDir = import_path9.default.resolve(DOCS_DIR), docsIndexPath = import_path9.default.join(docsDir, DOCS_INDEX_FILE);
2768
+ ensurePathExists(
2769
+ docsIndexPath,
2770
+ [
2771
+ `Documentation not found: /docs/${DOCS_INDEX_FILE}.`,
2772
+ `Add your docs to /docs/${DOCS_INDEX_FILE} before publishing, or remove the "docsUrl" field from manifest.json if you don't want to include documentation.`,
2773
+ `Learn more: ${DOCS_GUIDE_URL}`
2774
+ ].join(`
2775
+ `)
2776
+ );
2777
+ }
2778
+ function hasLocalDocs() {
2779
+ let docsIndexPath = import_path9.default.join(import_path9.default.resolve(DOCS_DIR), DOCS_INDEX_FILE);
2780
+ return import_fs9.default.existsSync(docsIndexPath);
2781
+ }
2781
2782
  function validateMarketplaceAssets() {
2782
2783
  let marketplaceDir = import_path9.default.resolve(MARKETPLACE_DIR);
2783
2784
  ensurePathExists(
@@ -2824,23 +2825,24 @@ function getMarketplaceHeaderImage() {
2824
2825
  filename: MARKETPLACE_HEADER_IMAGE_FILE
2825
2826
  };
2826
2827
  }
2827
- var import_fs9, import_path9, MARKETPLACE_DIR, MARKETPLACE_INDEX_FILE, MARKETPLACE_HEADER_IMAGE_FILE, PUBLIC_DIR, PUBLIC_LOGO_FILE, MANIFEST_FILE2, DIST_DIR, SRC_DIR, ensurePathExists, validateManifestPublishingFields, ensureManifestCatalogFields, marketplacePaths, init_marketplace = __esm({
2828
+ var import_fs9, import_path9, MARKETPLACE_DIR, MARKETPLACE_INDEX_FILE, MARKETPLACE_HEADER_IMAGE_FILE, PUBLIC_DIR, PUBLIC_LOGO_FILE, MANIFEST_FILE2, DIST_DIR, SRC_DIR, DOCS_DIR, DOCS_INDEX_FILE, DOCS_GUIDE_URL, ensurePathExists, ensureManifestCatalogFields, validateManifestPublishingFields, marketplacePaths, init_marketplace = __esm({
2828
2829
  "src/utils/marketplace.ts"() {
2829
2830
  "use strict";
2830
2831
  import_fs9 = __toESM(require("fs")), import_path9 = __toESM(require("path"));
2831
2832
  init_manifestManager();
2832
2833
  init_logger();
2833
- MARKETPLACE_DIR = "marketplace", MARKETPLACE_INDEX_FILE = "index.md", MARKETPLACE_HEADER_IMAGE_FILE = "header-image.jpg", PUBLIC_DIR = "public", PUBLIC_LOGO_FILE = "logo.svg", MANIFEST_FILE2 = "manifest.json", DIST_DIR = "dist", SRC_DIR = "src", ensurePathExists = (targetPath, errorMessage) => {
2834
+ MARKETPLACE_DIR = "marketplace", MARKETPLACE_INDEX_FILE = "index.md", MARKETPLACE_HEADER_IMAGE_FILE = "header-image.jpg", PUBLIC_DIR = "public", PUBLIC_LOGO_FILE = "logo.svg", MANIFEST_FILE2 = "manifest.json", DIST_DIR = "dist", SRC_DIR = "src", DOCS_DIR = "docs", DOCS_INDEX_FILE = "index.md", DOCS_GUIDE_URL = "https://diplodoc.com/docs/ru/", ensurePathExists = (targetPath, errorMessage) => {
2834
2835
  import_fs9.default.existsSync(targetPath) || (logger_default.error(errorMessage), process.exit(1));
2835
- }, validateManifestPublishingFields = async () => {
2836
- let manifest = await manifestManager.load();
2837
- ensureManifestCatalogFields(manifest);
2838
- }, ensureManifestCatalogFields = (manifest) => {
2836
+ };
2837
+ ensureManifestCatalogFields = (manifest) => {
2839
2838
  (!manifest.name?.ru || !manifest.name?.en) && (logger_default.error(
2840
2839
  'Manifest field "name" is required for publishing. Add localized "name.ru" and "name.en" to ./manifest.json.'
2841
2840
  ), process.exit(1)), (!manifest.description?.ru || !manifest.description?.en) && (logger_default.error(
2842
2841
  'Manifest field "description" is required for publishing. Add localized "description.ru" and "description.en" to ./manifest.json.'
2843
2842
  ), process.exit(1));
2843
+ }, validateManifestPublishingFields = async () => {
2844
+ let manifest = await manifestManager.load();
2845
+ ensureManifestCatalogFields(manifest);
2844
2846
  };
2845
2847
  marketplacePaths = {
2846
2848
  distDir: DIST_DIR,
@@ -2895,6 +2897,14 @@ var import_fs10, import_path10, import_archiver, init_buildArchive = __esm({
2895
2897
  }
2896
2898
  });
2897
2899
 
2900
+ // src/utils/constants/docs.ts
2901
+ var localDocsUrl, init_docs = __esm({
2902
+ "src/utils/constants/docs.ts"() {
2903
+ "use strict";
2904
+ localDocsUrl = "/docs/index.html";
2905
+ }
2906
+ });
2907
+
2898
2908
  // src/utils/execCommand.ts
2899
2909
  var import_execa, execCommand, init_execCommand = __esm({
2900
2910
  "src/utils/execCommand.ts"() {
@@ -2961,18 +2971,77 @@ var build, init_build = __esm({
2961
2971
  }
2962
2972
  });
2963
2973
 
2974
+ // src/commands/utils/buildDocs.ts
2975
+ async function buildDocs(outputPath) {
2976
+ validateDocs();
2977
+ let pluginDir = resolveProjectRoot(), inputDir = import_path11.default.join(pluginDir, "docs"), outputDir = outputPath ? import_path11.default.join(pluginDir, outputPath) : import_path11.default.join(pluginDir, "dist", "docs"), originalCwd = process.cwd();
2978
+ process.chdir(inputDir);
2979
+ try {
2980
+ let report = await (0, import_cli.run)(["build", "--input", inputDir, "--output", outputDir]);
2981
+ if (report.code !== 0)
2982
+ throw new Error(`YFM build failed with exit code ${report.code}`);
2983
+ } finally {
2984
+ process.chdir(originalCwd);
2985
+ }
2986
+ }
2987
+ var import_path11, import_cli, init_buildDocs = __esm({
2988
+ "src/commands/utils/buildDocs.ts"() {
2989
+ "use strict";
2990
+ import_path11 = __toESM(require("path")), import_cli = require("@diplodoc/cli");
2991
+ init_marketplace();
2992
+ init_project();
2993
+ }
2994
+ });
2995
+
2996
+ // src/commands/submit/legalNotice.ts
2997
+ function showSubmitLegalNotice() {
2998
+ logger_default.separator(), logger_default.info("Legal notice / \u042E\u0440\u0438\u0434\u0438\u0447\u0435\u0441\u043A\u043E\u0435 \u0443\u0432\u0435\u0434\u043E\u043C\u043B\u0435\u043D\u0438\u0435"), logger_default.info(SUBMIT_LEGAL_NOTICE_RU), logger_default.info(SUBMIT_LEGAL_NOTICE_EN), logger_default.separator();
2999
+ }
3000
+ var SUBMIT_LEGAL_NOTICE_RU, SUBMIT_LEGAL_NOTICE_EN, init_legalNotice = __esm({
3001
+ "src/commands/submit/legalNotice.ts"() {
3002
+ "use strict";
3003
+ init_logger();
3004
+ SUBMIT_LEGAL_NOTICE_RU = "\u0418\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u044F \u0438\u043D\u0441\u0442\u0440\u0443\u043C\u0435\u043D\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043E\u0442\u043A\u0438 \u0438 \u043E\u0442\u043F\u0440\u0430\u0432\u043B\u044F\u044F \u041F\u043B\u0430\u0433\u0438\u043D \u043D\u0430 \u041C\u043E\u0434\u0435\u0440\u0430\u0446\u0438\u044E \u0434\u043B\u044F \u0446\u0435\u043B\u0435\u0439 \u0440\u0430\u0437\u043C\u0435\u0449\u0435\u043D\u0438\u044F \u0432 \u041A\u0430\u0442\u0430\u043B\u043E\u0433\u0435 \u041F\u043B\u0430\u0433\u0438\u043D\u043E\u0432 \u0432\u044B \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u0435\u0442\u0435, \u0447\u0442\u043E \u043E\u0437\u043D\u0430\u043A\u043E\u043C\u043B\u0435\u043D\u044B \u0438 \u0441\u043E\u0433\u043B\u0430\u0441\u043D\u044B \u0441\u043E \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u043C\u0438 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430\u043C\u0438: \u0423\u0441\u043B\u043E\u0432\u0438\u044F \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u0438\u044F \u043A\u0430\u0442\u0430\u043B\u043E\u0433\u0430 \u043F\u043B\u0430\u0433\u0438\u043D\u043E\u0432 \u0434\u043B\u044F \u0421\u0435\u0440\u0432\u0438\u0441\u043E\u0432 \u042F\u043D\u0434\u0435\u043A\u0441 360 (https://yandex.ru/legal/360_plugin_termsofuse), \u0421\u043E\u0433\u043B\u0430\u0448\u0435\u043D\u0438\u0435 \u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043E\u0442\u0447\u0438\u043A\u043E\u043C \u043F\u043B\u0430\u0433\u0438\u043D\u043E\u0432 (\u043F\u0430\u0431\u043B\u0438\u0448\u0435\u0440\u043E\u043C) \u0434\u043B\u044F \u043A\u0430\u0442\u0430\u043B\u043E\u0433\u0430 \u043F\u043B\u0430\u0433\u0438\u043D\u043E\u0432 \u0421\u0435\u0440\u0432\u0438\u0441\u043E\u0432 \u042F\u043D\u0434\u0435\u043A\u0441 360 (https://yandex.ru/legal/360_plugin_dev_agreement).", SUBMIT_LEGAL_NOTICE_EN = "By using the development tool and submitting the Plugin for Moderation for the purpose of placement in the Plugin Catalog, you acknowledge that you have read and agree to the following documents: Terms of Use of the Plugin Catalog for Yandex 360 Services ( https://yandex.ru/legal/360_plugin_termsofuse ), Plugin Developer (Publisher) Agreement for the Plugin Catalog of Yandex 360 Services ( https://yandex.ru/legal/360_plugin_dev_agreement ).";
3005
+ }
3006
+ });
3007
+
3008
+ // src/utils/urlGuards.ts
3009
+ var isLocalDocsUrl, isExternalDocsUrl, init_urlGuards = __esm({
3010
+ "src/utils/urlGuards.ts"() {
3011
+ "use strict";
3012
+ isLocalDocsUrl = (docsUrl) => docsUrl ? !/^https?:\/\//i.test(docsUrl) : !1, isExternalDocsUrl = (docsUrl) => docsUrl ? /^https?:\/\//i.test(docsUrl) : !1;
3013
+ }
3014
+ });
3015
+
3016
+ // src/commands/submit/utils/resolveBuildDocsDecision.ts
3017
+ function resolveBuildDocsDecision(docsUrl) {
3018
+ if (isExternalDocsUrl(docsUrl))
3019
+ return { shouldBuild: !1, autoDetected: !1 };
3020
+ if (isLocalDocsUrl(docsUrl))
3021
+ return { shouldBuild: !0, autoDetected: !1 };
3022
+ let detected = hasLocalDocs();
3023
+ return { shouldBuild: detected, autoDetected: detected };
3024
+ }
3025
+ var init_resolveBuildDocsDecision = __esm({
3026
+ "src/commands/submit/utils/resolveBuildDocsDecision.ts"() {
3027
+ "use strict";
3028
+ init_marketplace();
3029
+ init_urlGuards();
3030
+ }
3031
+ });
3032
+
2964
3033
  // src/utils/pluginPackageScripts.ts
2965
3034
  function readPluginPackageScripts(cwd = process.cwd()) {
2966
- let packageJsonPath = import_path11.default.join(cwd, "package.json");
3035
+ let packageJsonPath = import_path12.default.join(cwd, "package.json");
2967
3036
  return import_fs11.default.existsSync(packageJsonPath) ? JSON.parse(import_fs11.default.readFileSync(packageJsonPath, "utf-8")).scripts ?? {} : null;
2968
3037
  }
2969
3038
  function hasPluginScript(name, cwd = process.cwd()) {
2970
3039
  return !!readPluginPackageScripts(cwd)?.[name];
2971
3040
  }
2972
- var import_fs11, import_path11, init_pluginPackageScripts = __esm({
3041
+ var import_fs11, import_path12, init_pluginPackageScripts = __esm({
2973
3042
  "src/utils/pluginPackageScripts.ts"() {
2974
3043
  "use strict";
2975
- import_fs11 = __toESM(require("fs")), import_path11 = __toESM(require("path"));
3044
+ import_fs11 = __toESM(require("fs")), import_path12 = __toESM(require("path"));
2976
3045
  }
2977
3046
  });
2978
3047
 
@@ -3004,8 +3073,8 @@ var import_picocolors3, stepStart, stepDone, runStep, runShellStep, init_runSubm
3004
3073
  console.info(`${import_picocolors3.default.cyan("\u25B8")} ${label}`);
3005
3074
  }, stepDone = (label) => {
3006
3075
  console.info(`${import_picocolors3.default.green("\u2713")} ${label}`), console.info("");
3007
- }, runStep = async (label, run) => {
3008
- stepStart(label), await run(), stepDone(label);
3076
+ }, runStep = async (label, run2) => {
3077
+ stepStart(label), await run2(), stepDone(label);
3009
3078
  }, runShellStep = async (label, command) => {
3010
3079
  stepStart(label), console.info(import_picocolors3.default.dim(` $ ${command}`)), await execCommand(command), stepDone(label);
3011
3080
  };
@@ -3047,9 +3116,9 @@ var readline, init_validateSlug = __esm({
3047
3116
 
3048
3117
  // src/commands/submit/platform.ts
3049
3118
  async function submitPlatform(options = {}) {
3050
- await runSubmitPrechecks({ skip: options.skipChecks });
3051
- let manifest = await manifestManager.load();
3052
- await build(), logger_default.info("\u{1F4E6} Creating archive...");
3119
+ applyPlatformAuthOptions(options), await runSubmitPrechecks({ skip: options.skipChecks });
3120
+ let manifest = await manifestManager.load(), { docsUrl } = manifest, { shouldBuild, autoDetected } = resolveBuildDocsDecision(docsUrl);
3121
+ shouldBuild && validateDocs(), logger_default.info("\u{1F4E6} Building plugin..."), await build(), shouldBuild && (logger_default.info("\u{1F4E6} Building docs..."), await buildDocs(), autoDetected && (logger_default.info(`\u{1F4DD} Writing docsUrl: "${localDocsUrl}" to manifest.json...`), await manifestManager.update({ docsUrl: localDocsUrl }))), logger_default.info("\u{1F4E6} Creating archive...");
3053
3122
  let archiveBuffer = await buildArchive(), archiveName = `${manifest.slug}-${manifest.version}.zip`, pluginId;
3054
3123
  if (manifest.id)
3055
3124
  pluginId = manifest.id, logger_default.info("\u{1F4E4} Updating plugin archive..."), await updatePluginArchive(pluginId, archiveBuffer, archiveName);
@@ -3062,7 +3131,7 @@ async function submitPlatform(options = {}) {
3062
3131
  let catalogEntry = await getMarketplaceCatalogEntry();
3063
3132
  logger_default.info("\u{1F4DD} Updating catalog entry from ./marketplace/index.md..."), await updateCatalogEntry(pluginId, catalogEntry);
3064
3133
  let headerImage = getMarketplaceHeaderImage();
3065
- logger_default.info("\u{1F5BC}\uFE0F Uploading catalog image from ./marketplace/header-image.jpg..."), await updateCatalogImage(pluginId, headerImage.buffer, headerImage.filename), await submitPlugin(pluginId, manifest.version), logger_default.success("Plugin submitted for review!"), logger_default.info(` Version : ${manifest.version}`), logger_default.newLine();
3134
+ logger_default.info("\u{1F5BC}\uFE0F Uploading catalog image from ./marketplace/header-image.jpg..."), await updateCatalogImage(pluginId, headerImage.buffer, headerImage.filename), showSubmitLegalNotice(), await submitPlugin(pluginId, manifest.version), logger_default.success("Plugin submitted for review!"), logger_default.info(` Version : ${manifest.version}`), logger_default.newLine();
3066
3135
  }
3067
3136
  var init_platform4 = __esm({
3068
3137
  "src/commands/submit/platform.ts"() {
@@ -3070,78 +3139,20 @@ var init_platform4 = __esm({
3070
3139
  init_platform();
3071
3140
  init_manifestManager();
3072
3141
  init_buildArchive();
3142
+ init_docs();
3073
3143
  init_logger();
3074
3144
  init_marketplace();
3075
3145
  init_pluginDisplay();
3076
3146
  init_build();
3147
+ init_platformAuth();
3148
+ init_buildDocs();
3149
+ init_legalNotice();
3150
+ init_resolveBuildDocsDecision();
3077
3151
  init_runSubmitPrechecks();
3078
3152
  init_validateSlug();
3079
3153
  }
3080
3154
  });
3081
3155
 
3082
- // src/core/cliConfig/registerCommand.ts
3083
- async function promptString(message, current) {
3084
- return (await (0, import_prompts.input)({
3085
- message: current ? `${message} (current: ${current})` : `${message} (optional)`,
3086
- default: current,
3087
- required: !1
3088
- }))?.trim() || void 0;
3089
- }
3090
- async function runConfigSet(cliName) {
3091
- let existing = readConfig() ?? {};
3092
- logger_default.info(
3093
- "Configure CLI overrides. Empty input clears the value (and falls back to defaults where applicable)."
3094
- );
3095
- let s3Endpoint = await promptString("S3 endpoint", existing.s3?.endpoint), s3Region = await promptString("S3 region", existing.s3?.region), mdsEndpoint = await promptString("MDS endpoint", existing.mds?.endpoint), productionStatic = await promptString(
3096
- "Production bucket (static)",
3097
- existing.buckets?.production?.static
3098
- ), productionConfig = await promptString(
3099
- "Production bucket (config)",
3100
- existing.buckets?.production?.config
3101
- ), pluginDownloadProduction = await promptString(
3102
- "Plugin download base URL",
3103
- existing.pluginDownloadBase?.production
3104
- ), platformBaseUrl = await promptString(
3105
- "Platform API base URL",
3106
- existing.api?.platformBaseUrl
3107
- ), oauthUrl = await promptString("OAuth token URL", existing.auth?.oauthUrl);
3108
- writeConfig({
3109
- s3: { endpoint: s3Endpoint, region: s3Region },
3110
- mds: { endpoint: mdsEndpoint },
3111
- buckets: {
3112
- production: { static: productionStatic, config: productionConfig }
3113
- },
3114
- pluginDownloadBase: { production: pluginDownloadProduction },
3115
- api: { platformBaseUrl },
3116
- auth: { oauthUrl }
3117
- }), logger_default.success(`Configuration saved \u2192 ${getConfigPath()}`), logger_default.info(`Inspect with "${cliName} config show" or revert with "${cliName} config clear".`);
3118
- }
3119
- function runConfigShow(cliName) {
3120
- let cfg = readConfig();
3121
- if (!cfg) {
3122
- logger_default.info(
3123
- `No configuration found at ${getConfigPath()}. Run "${cliName} config set" to create one.`
3124
- );
3125
- return;
3126
- }
3127
- logger_default.info(`Configuration at ${getConfigPath()}:`), logger_default.info(JSON.stringify(cfg, null, 2));
3128
- }
3129
- function runConfigClear() {
3130
- clearConfig(), logger_default.success(`Configuration removed (${getConfigPath()})`);
3131
- }
3132
- function registerConfigCommand(program, cliName) {
3133
- let config = program.command("config").description("manage CLI configuration");
3134
- config.command("set").description("set CLI configuration values interactively").action(() => runConfigSet(cliName)), config.command("show").description("display current CLI configuration").action(() => runConfigShow(cliName)), config.command("clear").description("remove stored CLI configuration").action(runConfigClear);
3135
- }
3136
- var import_prompts, init_registerCommand = __esm({
3137
- "src/core/cliConfig/registerCommand.ts"() {
3138
- "use strict";
3139
- import_prompts = require("@inquirer/prompts");
3140
- init_logger();
3141
- init_manager();
3142
- }
3143
- });
3144
-
3145
3156
  // src/utils/withErrorHandling.ts
3146
3157
  function withErrorHandling(fn) {
3147
3158
  return async (...args) => {
@@ -3184,10 +3195,10 @@ async function loginExternal() {
3184
3195
  console.info(
3185
3196
  import_picocolors4.default.dim("Get your OAuth token at: ") + import_picocolors4.default.cyan(`${ESC}]8;;${tokenUrl}${BEL}${tokenUrl}${ESC}]8;;${BEL}`)
3186
3197
  ), console.info("");
3187
- let token = await (0, import_prompts2.input)({
3198
+ let token = await (0, import_prompts.input)({
3188
3199
  message: "Enter your OAuth token:",
3189
3200
  required: !0
3190
- }), orgId = await (0, import_prompts2.input)({
3201
+ }), orgId = await (0, import_prompts.input)({
3191
3202
  message: "Enter your Organization ID (X-Org-ID):",
3192
3203
  required: !0
3193
3204
  });
@@ -3208,10 +3219,10 @@ function logoutExternal() {
3208
3219
  }
3209
3220
  logger_default.success("Successfully logged out.");
3210
3221
  }
3211
- var import_prompts2, import_picocolors4, ESC, BEL, init_login = __esm({
3222
+ var import_prompts, import_picocolors4, ESC, BEL, init_login = __esm({
3212
3223
  "src/distributions/external/login.ts"() {
3213
3224
  "use strict";
3214
- import_prompts2 = require("@inquirer/prompts"), import_picocolors4 = __toESM(require("picocolors"));
3225
+ import_prompts = require("@inquirer/prompts"), import_picocolors4 = __toESM(require("picocolors"));
3215
3226
  init_manager();
3216
3227
  init_logger();
3217
3228
  init_authManager();
@@ -3226,11 +3237,11 @@ __export(registerCommands_exports, {
3226
3237
  registerDistributionCommands: () => registerDistributionCommands
3227
3238
  });
3228
3239
  function registerDistributionCommands(program) {
3229
- registerConfigCommand(program, CLI_NAME), program.command("login").description("save your Yandex Tracker OAuth token (request it via Tracker support)").action(withErrorHandling(loginExternal)), program.command("logout").description("remove saved OAuth token").action(
3240
+ program.command("login").description("save your Yandex Tracker OAuth token (request it via Tracker support)").action(withErrorHandling(loginExternal)), program.command("logout").description("remove saved OAuth token").action(
3230
3241
  withErrorHandling(async () => {
3231
3242
  logoutExternal();
3232
3243
  })
3233
- ), program.command("submit").description("build plugin and submit it to the platform for review").addOption(skipChecksOption).action(withErrorHandling(submitPlatform)), program.command("doctor").description("validate local plugin project, external config and auth").option("--network", "verify OAuth token with Tracker /myself", !1).option("--publish", "treat publish-readiness checks as failures", !1).option("--json", "machine-readable output", !1).action((options) => withErrorHandling(doctor)(options)), program.command("list").description("list all your plugins and their moderation status").action(withErrorHandling(listPlatform)), program.command("info [plugin-id]").description("show plugin status (uses plugin id from manifest if not provided)").action(withErrorHandling(infoPlatform));
3244
+ ), program.command("submit").description("build plugin and submit it to the platform for review").addOption(skipChecksOption).addOption(iamTokenOption).action(withErrorHandling(submitPlatform)), program.command("doctor").description("validate local plugin project and auth").option("--network", "verify OAuth token against the Platform API", !1).option("--publish", "treat publish-readiness checks as failures", !1).option("--json", "machine-readable output", !1).action((options) => withErrorHandling(doctor)(options)), program.command("list").description("list all your plugins and their moderation status").addOption(iamTokenOption).action(withErrorHandling(listPlatform)), program.command("info [plugin-id]").description("show plugin status (uses plugin id from manifest if not provided)").addOption(iamTokenOption).action(withErrorHandling(infoPlatform));
3234
3245
  }
3235
3246
  var init_registerCommands = __esm({
3236
3247
  "src/distributions/external/registerCommands.ts"() {
@@ -3238,17 +3249,16 @@ var init_registerCommands = __esm({
3238
3249
  init_doctor();
3239
3250
  init_platform2();
3240
3251
  init_platform3();
3252
+ init_platformAuth();
3241
3253
  init_options();
3242
3254
  init_platform4();
3243
- init_registerCommand();
3244
3255
  init_withErrorHandling();
3245
3256
  init_login();
3246
- init_meta();
3247
3257
  }
3248
3258
  });
3249
3259
 
3250
3260
  // src/index.ts
3251
- var import_commander2 = require("commander");
3261
+ var import_commander3 = require("commander");
3252
3262
  init_meta2();
3253
3263
 
3254
3264
  // src/distribution/registerCommands.ts
@@ -3256,7 +3266,7 @@ init_flag();
3256
3266
  var impl6 = (init_registerCommands(), __toCommonJS(registerCommands_exports)), { registerDistributionCommands: registerDistributionCommands2 } = impl6;
3257
3267
 
3258
3268
  // src/utils/checkUpdate.ts
3259
- var import_node_fetch3 = __toESM(require("node-fetch"));
3269
+ var import_node_fetch2 = __toESM(require("node-fetch"));
3260
3270
  init_hosts2();
3261
3271
  init_logger();
3262
3272
  var SEMVER_RE = /^(\d+)\.(\d+)\.(\d+)$/, DIAGNOSTIC_FLAGS = /* @__PURE__ */ new Set(["--version", "-V", "--help", "-h", "help"]), parse = (v) => {
@@ -3272,7 +3282,7 @@ var SEMVER_RE = /^(\d+)\.(\d+)\.(\d+)$/, DIAGNOSTIC_FLAGS = /* @__PURE__ */ new
3272
3282
  let current = parse(version);
3273
3283
  if (current)
3274
3284
  try {
3275
- let response = await (0, import_node_fetch3.default)(`${info2.registryUrl}/${info2.packageName}/latest`);
3285
+ let response = await (0, import_node_fetch2.default)(`${info2.registryUrl}/${info2.packageName}/latest`);
3276
3286
  if (!response.ok) return;
3277
3287
  let json = await response.json(), latest = parse(json.version);
3278
3288
  if (!latest) return;
@@ -3300,14 +3310,22 @@ function shouldRunUpdateCheck(argv) {
3300
3310
  // src/index.ts
3301
3311
  init_build();
3302
3312
 
3313
+ // src/commands/build-docs.ts
3314
+ init_logger();
3315
+ init_buildDocs();
3316
+ var buildDocs2 = async () => {
3317
+ logger_default.info("\u{1F4E6} Building docs..."), await buildDocs("docs-build"), logger_default.info("You can see your docs by opening ./docs-build/index.html in your browser");
3318
+ };
3319
+
3303
3320
  // src/commands/create/index.ts
3304
- var path18 = __toESM(require("path")), import_prompts3 = require("@inquirer/prompts");
3305
- init_constants();
3321
+ var path20 = __toESM(require("path")), import_prompts2 = require("@inquirer/prompts");
3322
+ init_platform();
3323
+ init_constants2();
3306
3324
  init_meta2();
3307
3325
  init_logger();
3308
3326
 
3309
3327
  // src/commands/create/templateChoices.ts
3310
- init_constants();
3328
+ init_constants2();
3311
3329
  var DEFERRED_TEMPLATE_REASON = "will be added later", DEFERRED_TEMPLATES = /* @__PURE__ */ new Set(["user-card-info", "user-card-calendar"]);
3312
3330
  function getTemplateChoices(service) {
3313
3331
  return TEMPLATES.filter((templateName) => TEMPLATE_SERVICE[templateName] === service).map(
@@ -3329,10 +3347,10 @@ ${import_picocolors5.default.dim("Press")} ${import_picocolors5.default.yellow("
3329
3347
  `;
3330
3348
 
3331
3349
  // src/commands/create/utils/initManifest.ts
3332
- var fs11 = __toESM(require("fs")), path13 = __toESM(require("path"));
3350
+ var fs12 = __toESM(require("fs")), path16 = __toESM(require("path"));
3333
3351
 
3334
3352
  // src/commands/create/utils/generateManifest.ts
3335
- init_constants();
3353
+ init_constants2();
3336
3354
  var FULL_CONTEXT_TEMPLATES = /* @__PURE__ */ new Set(["user-card-info", "user-card-calendar"]);
3337
3355
  function buildSlots(template, slotTitle) {
3338
3356
  let slotNames = TEMPLATE_SLOTS[template];
@@ -3360,19 +3378,46 @@ var generateManifest = (answers) => ({
3360
3378
  ru: answers.pluginDescription,
3361
3379
  en: answers.pluginDescription
3362
3380
  },
3381
+ categories: answers.categories,
3363
3382
  permissions: answers.permissions,
3364
3383
  support: [{ type: "email", value: answers.supportEmail }],
3365
3384
  slots: buildSlots(answers.template, answers.slotTitle)
3366
3385
  });
3367
3386
 
3387
+ // src/commands/create/utils/generateManifestSchema.ts
3388
+ var fs11 = __toESM(require("fs")), path15 = __toESM(require("path"));
3389
+
3390
+ // src/utils/getProjectPath.ts
3391
+ var import_path13 = __toESM(require("path")), isDevelopment = () => __dirname.includes("/src/"), getProjectPath = (relativePath) => isDevelopment() ? import_path13.default.resolve(__dirname, "..", "..", relativePath) : import_path13.default.resolve(__dirname, relativePath), getTemplatesBaseDir = () => getProjectPath("templates"), getTemplatePath = (filename) => import_path13.default.join(getTemplatesBaseDir(), "_shared", filename), getOverlayTemplatePath = (overlayDir, filename) => import_path13.default.join(getTemplatesBaseDir(), overlayDir, filename);
3392
+
3393
+ // src/commands/create/utils/generateManifestSchema.ts
3394
+ function generateManifestSchema(categories, targetDir) {
3395
+ let baseSchemaPath = path15.join(getTemplatesBaseDir(), "_shared", "manifest.schema.json"), baseSchema = JSON.parse(fs11.readFileSync(baseSchemaPath, "utf-8")), categoriesProperty = {
3396
+ type: "array",
3397
+ description: "Categories this plugin belongs to",
3398
+ items: {
3399
+ type: "string",
3400
+ enum: categories.items.map((c) => c.slug)
3401
+ },
3402
+ uniqueItems: !0
3403
+ }, patchedSchema = {
3404
+ ...baseSchema,
3405
+ properties: {
3406
+ ...baseSchema.properties,
3407
+ categories: categoriesProperty
3408
+ }
3409
+ }, schemaPath = path15.join(targetDir, "manifest.schema.json");
3410
+ fs11.writeFileSync(schemaPath, JSON.stringify(patchedSchema, null, 2), "utf-8");
3411
+ }
3412
+
3368
3413
  // src/commands/create/utils/initManifest.ts
3369
- var initManifest = ({ answers, targetDir }) => {
3370
- let generatedManifest = generateManifest(answers), manifestPath = path13.join(targetDir, "manifest.json");
3371
- fs11.writeFileSync(manifestPath, JSON.stringify(generatedManifest, null, 2), "utf-8");
3414
+ var initManifest = ({ answers, targetDir, categories }) => {
3415
+ let generatedManifest = generateManifest(answers), manifestPath = path16.join(targetDir, "manifest.json");
3416
+ fs12.writeFileSync(manifestPath, JSON.stringify(generatedManifest, null, 2), "utf-8"), generateManifestSchema(categories, targetDir);
3372
3417
  };
3373
3418
 
3374
3419
  // src/commands/create/utils/initTemplate.ts
3375
- var fs14 = __toESM(require("fs")), path17 = __toESM(require("path"));
3420
+ var fs15 = __toESM(require("fs")), path19 = __toESM(require("path"));
3376
3421
 
3377
3422
  // src/distribution/templateSubstitution.ts
3378
3423
  init_flag();
@@ -3383,7 +3428,7 @@ var isInternal = !1, templateDeps = [
3383
3428
  ], overlayDirName = isInternal ? "_internal" : "_external";
3384
3429
 
3385
3430
  // src/utils/copyDirectory.ts
3386
- var fs12 = __toESM(require("fs")), import_path12 = __toESM(require("path")), import_tinyglobby2 = require("tinyglobby"), resolveTargetFileName = (file) => file.endsWith(".template") ? "." + file.replace(".template", "") : file, copyDirectory = async (sourceDir, targetDir) => {
3431
+ var fs13 = __toESM(require("fs")), import_path14 = __toESM(require("path")), import_tinyglobby2 = require("tinyglobby"), resolveTargetFileName = (file) => file.endsWith(".template") ? "." + file.replace(".template", "") : file, copyDirectory = async (sourceDir, targetDir) => {
3387
3432
  let files = await (0, import_tinyglobby2.glob)(["**/*"], {
3388
3433
  cwd: sourceDir,
3389
3434
  onlyFiles: !0,
@@ -3391,34 +3436,31 @@ var fs12 = __toESM(require("fs")), import_path12 = __toESM(require("path")), imp
3391
3436
  });
3392
3437
  await Promise.all(
3393
3438
  files.map(async (file) => {
3394
- let sourcePath = import_path12.default.join(sourceDir, file), targetFile = resolveTargetFileName(file), targetPath = import_path12.default.join(targetDir, targetFile);
3395
- await fs12.promises.mkdir(import_path12.default.dirname(targetPath), { recursive: !0 });
3396
- let content = await fs12.promises.readFile(sourcePath);
3397
- await fs12.promises.writeFile(targetPath, content);
3439
+ let sourcePath = import_path14.default.join(sourceDir, file), targetFile = resolveTargetFileName(file), targetPath = import_path14.default.join(targetDir, targetFile);
3440
+ await fs13.promises.mkdir(import_path14.default.dirname(targetPath), { recursive: !0 });
3441
+ let content = await fs13.promises.readFile(sourcePath);
3442
+ await fs13.promises.writeFile(targetPath, content);
3398
3443
  })
3399
3444
  );
3400
3445
  };
3401
3446
 
3402
- // src/utils/getProjectPath.ts
3403
- var import_path13 = __toESM(require("path")), isDevelopment = () => __dirname.includes("/src/"), getProjectPath = (relativePath) => isDevelopment() ? import_path13.default.resolve(__dirname, "..", "..", relativePath) : import_path13.default.resolve(__dirname, relativePath), getTemplatesBaseDir = () => getProjectPath("templates"), getTemplatePath = (filename) => import_path13.default.join(getTemplatesBaseDir(), "_shared", filename), getOverlayTemplatePath = (overlayDir, filename) => import_path13.default.join(getTemplatesBaseDir(), overlayDir, filename);
3404
-
3405
3447
  // src/commands/create/utils/initTemplate.ts
3406
3448
  init_logger();
3407
3449
 
3408
3450
  // src/commands/create/utils/updatePackageJson.ts
3409
- var fs13 = __toESM(require("fs")), path16 = __toESM(require("path")), updatePackageJson = (targetDir, packageSlug) => {
3410
- let packageJsonPath = path16.join(targetDir, "package.json");
3411
- if (fs13.existsSync(packageJsonPath)) {
3412
- let packageJson = JSON.parse(fs13.readFileSync(packageJsonPath, "utf-8"));
3413
- packageJson.name = packageSlug, fs13.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 4) + `
3451
+ var fs14 = __toESM(require("fs")), path18 = __toESM(require("path")), updatePackageJson = (targetDir, packageSlug) => {
3452
+ let packageJsonPath = path18.join(targetDir, "package.json");
3453
+ if (fs14.existsSync(packageJsonPath)) {
3454
+ let packageJson = JSON.parse(fs14.readFileSync(packageJsonPath, "utf-8"));
3455
+ packageJson.name = packageSlug, fs14.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 4) + `
3414
3456
  `);
3415
3457
  }
3416
3458
  };
3417
3459
 
3418
3460
  // src/commands/create/utils/initTemplate.ts
3419
3461
  var initTemplate = async ({ answers, targetDir }) => {
3420
- fs14.existsSync(targetDir) || fs14.mkdirSync(targetDir, { recursive: !0 });
3421
- let templatesBaseDir = getTemplatesBaseDir(), templatesDir = path17.join(templatesBaseDir, answers.template), sharedDir = path17.join(templatesBaseDir, "_shared"), overlayDir = path17.join(templatesBaseDir, overlayDirName);
3462
+ fs15.existsSync(targetDir) || fs15.mkdirSync(targetDir, { recursive: !0 });
3463
+ let templatesBaseDir = getTemplatesBaseDir(), templatesDir = path19.join(templatesBaseDir, answers.template), sharedDir = path19.join(templatesBaseDir, "_shared"), overlayDir = path19.join(templatesBaseDir, overlayDirName);
3422
3464
  await copyDirectory(sharedDir, targetDir), await copyDirectory(overlayDir, targetDir), await copyDirectory(templatesDir, targetDir), updatePackageJson(targetDir, answers.packageSlug), logger_default.info("Created template with marketplace publication requirements."), logger_default.info(
3423
3465
  "Before publishing, add ./marketplace/index.md, ./marketplace/header-image.jpg (784:325), and ./public/logo.svg (square)."
3424
3466
  );
@@ -3428,20 +3470,20 @@ var initTemplate = async ({ answers, targetDir }) => {
3428
3470
  var DEFAULT_VERSION = "0.0.1";
3429
3471
  async function create() {
3430
3472
  logger_default.info(getWelcomeMessage(process.cwd()));
3431
- let packageSlug = await (0, import_prompts3.input)({
3473
+ let packageSlug = await (0, import_prompts2.input)({
3432
3474
  message: "Enter app slug (e.g., my-tracker-plugin):",
3433
3475
  required: !0
3434
- }), pluginName = await (0, import_prompts3.input)({
3476
+ }), pluginName = await (0, import_prompts2.input)({
3435
3477
  message: "Enter plugin name:",
3436
3478
  required: !0
3437
- }), pluginDescription = await (0, import_prompts3.input)({
3479
+ }), pluginDescription = await (0, import_prompts2.input)({
3438
3480
  message: "Enter plugin description:",
3439
3481
  required: !0
3440
- }), supportEmail = await (0, import_prompts3.input)({
3482
+ }), supportEmail = await (0, import_prompts2.input)({
3441
3483
  message: "Enter support email:",
3442
3484
  required: !0,
3443
3485
  validate: (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value) || "Please enter a valid email address"
3444
- }), service = CREATE_SERVICES2.length === 1 ? CREATE_SERVICES2[0] : await (0, import_prompts3.select)({
3486
+ }), service = CREATE_SERVICES2.length === 1 ? CREATE_SERVICES2[0] : await (0, import_prompts2.select)({
3445
3487
  message: "Select a service:",
3446
3488
  choices: CREATE_SERVICES2.map((serviceName) => ({
3447
3489
  name: serviceName,
@@ -3455,10 +3497,16 @@ async function create() {
3455
3497
  );
3456
3498
  return;
3457
3499
  }
3458
- let template = await (0, import_prompts3.select)({
3500
+ let template = await (0, import_prompts2.select)({
3459
3501
  message: "Select a template:",
3460
3502
  choices: templateChoices
3461
- }), dataPermissions = await (0, import_prompts3.checkbox)({
3503
+ }), categoriesResponse = await getPluginCategories(), chosenCategories = await (0, import_prompts2.checkbox)({
3504
+ message: "Select a category:",
3505
+ choices: categoriesResponse.items.map((category) => ({
3506
+ name: category.name.en,
3507
+ value: category.slug
3508
+ }))
3509
+ }), dataPermissions = await (0, import_prompts2.checkbox)({
3462
3510
  message: "Select data permissions (some popular options):",
3463
3511
  choices: TOP_DATA_PERMISSIONS.map((permission) => ({
3464
3512
  name: permission,
@@ -3471,25 +3519,27 @@ async function create() {
3471
3519
  pluginDescription,
3472
3520
  supportEmail,
3473
3521
  service,
3522
+ categories: chosenCategories,
3474
3523
  template,
3475
3524
  permissions: {
3476
3525
  data: dataPermissions
3477
3526
  },
3478
3527
  version: DEFAULT_VERSION
3479
- }, targetDir = path18.join(process.cwd(), answers.packageSlug);
3528
+ }, targetDir = path20.join(process.cwd(), answers.packageSlug);
3480
3529
  await initTemplate({
3481
3530
  answers,
3482
3531
  targetDir
3483
3532
  }), initManifest({
3484
3533
  answers,
3485
- targetDir
3534
+ targetDir,
3535
+ categories: categoriesResponse
3486
3536
  }), logger_default.newLine(), logger_default.success("\u2705 Plugin created successfully!"), logger_default.info("\u{1F680} To start development:"), logger_default.commands("", [`cd ${answers.packageSlug}`, "npm install", `${CLI_NAME2} debug`]), logger_default.info(
3487
3537
  "\u{1F4CC} Important: After running debug, the plugin will be available in the Tracker interface, not at localhost. Open Tracker and check the plugin in the appropriate context."
3488
3538
  );
3489
3539
  }
3490
3540
 
3491
3541
  // src/commands/debug/index.ts
3492
- var import_fs15 = __toESM(require("fs")), import_path17 = __toESM(require("path"));
3542
+ var import_fs15 = __toESM(require("fs")), import_path18 = __toESM(require("path"));
3493
3543
  init_manifestManager();
3494
3544
 
3495
3545
  // src/core/s3config/constants.ts
@@ -3513,7 +3563,7 @@ var registerCleanup = (cleanup) => {
3513
3563
  init_templateCommands();
3514
3564
 
3515
3565
  // src/commands/debug/utils/createDebugConfig.ts
3516
- var import_fs12 = __toESM(require("fs")), import_path14 = __toESM(require("path"));
3566
+ var import_fs12 = __toESM(require("fs")), import_path15 = __toESM(require("path"));
3517
3567
  init_manifestManager();
3518
3568
 
3519
3569
  // src/utils/convertManifestToConfig.ts
@@ -3561,12 +3611,12 @@ var convertManifestToConfig = (manifest, environment) => {
3561
3611
 
3562
3612
  // src/commands/debug/utils/createDebugConfig.ts
3563
3613
  var createDebugConfig = async () => {
3564
- let manifest = await manifestManager.load(), config = convertManifestToConfig(manifest, "debug"), configPath = import_path14.default.join(process.cwd(), CONFIG_FILE_NAME);
3614
+ let manifest = await manifestManager.load(), config = convertManifestToConfig(manifest, "debug"), configPath = import_path15.default.join(process.cwd(), CONFIG_FILE_NAME);
3565
3615
  import_fs12.default.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
3566
3616
  };
3567
3617
 
3568
3618
  // src/commands/debug/utils/lockFile.ts
3569
- var import_fs13 = __toESM(require("fs")), import_path15 = __toESM(require("path")), LOCK_FILE_NAME = ".yaweavix-debug.lock", getLockFilePath = () => import_path15.default.join(process.cwd(), LOCK_FILE_NAME), getRunningDebugPid = () => {
3619
+ var import_fs13 = __toESM(require("fs")), import_path16 = __toESM(require("path")), LOCK_FILE_NAME = ".yaweavix-debug.lock", getLockFilePath = () => import_path16.default.join(process.cwd(), LOCK_FILE_NAME), getRunningDebugPid = () => {
3570
3620
  let lockPath = getLockFilePath();
3571
3621
  if (!import_fs13.default.existsSync(lockPath))
3572
3622
  return null;
@@ -3591,11 +3641,11 @@ var import_fs13 = __toESM(require("fs")), import_path15 = __toESM(require("path"
3591
3641
  };
3592
3642
 
3593
3643
  // src/commands/debug/utils/watchManifest.ts
3594
- var import_fs14 = __toESM(require("fs")), import_path16 = __toESM(require("path"));
3644
+ var import_fs14 = __toESM(require("fs")), import_path17 = __toESM(require("path"));
3595
3645
  init_manifestManager();
3596
3646
  init_logger();
3597
3647
  var watchManifest = () => {
3598
- let manifestPath = import_path16.default.join(process.cwd(), "manifest.json"), debounceTimer = null, watcher = import_fs14.default.watch(manifestPath, async (eventType) => {
3648
+ let manifestPath = import_path17.default.join(process.cwd(), "manifest.json"), debounceTimer = null, watcher = import_fs14.default.watch(manifestPath, async (eventType) => {
3599
3649
  eventType === "change" && (debounceTimer && clearTimeout(debounceTimer), debounceTimer = setTimeout(async () => {
3600
3650
  try {
3601
3651
  logger_default.newLine(), logger_default.info("Manifest file changed, validating..."), await manifestManager.validate(), logger_default.info("Regenerating debug config..."), await createDebugConfig(), logger_default.success("Debug config regenerated successfully");
@@ -3619,7 +3669,7 @@ Please stop the existing instance before starting a new one.
3619
3669
  If you lost the terminal tab, you can kill the process with:
3620
3670
  kill ${runningPid}`
3621
3671
  ), process.exit(1));
3622
- let configPath = import_path17.default.join(process.cwd(), CONFIG_FILE_NAME);
3672
+ let configPath = import_path18.default.join(process.cwd(), CONFIG_FILE_NAME);
3623
3673
  options.lint && await manifestManager.validate(), await createDebugConfig();
3624
3674
  let watcher = watchManifest(), cleanup = () => {
3625
3675
  watcher.close(), import_fs15.default.existsSync(configPath) && import_fs15.default.unlinkSync(configPath), removeLockFile();
@@ -3638,15 +3688,16 @@ async function lint() {
3638
3688
 
3639
3689
  // src/commands/up/index.ts
3640
3690
  var import_fs18 = require("fs"), import_promises4 = require("fs/promises");
3691
+ init_platform();
3641
3692
  init_execCommand();
3642
3693
 
3643
3694
  // src/commands/up/utils/copyTemplateFiles.ts
3644
- var import_fs16 = require("fs"), import_promises2 = require("fs/promises"), import_path18 = __toESM(require("path"));
3695
+ var import_fs16 = require("fs"), import_promises2 = require("fs/promises"), import_path19 = __toESM(require("path"));
3645
3696
  var copyTemplateFiles = async (files) => {
3646
3697
  await Promise.all(
3647
3698
  files.map(async (file) => {
3648
3699
  let templatePath, targetPath, force = !1;
3649
- typeof file == "string" ? (templatePath = getTemplatePath(file), targetPath = `./${file}`) : (templatePath = file.sourcePath ?? getTemplatePath(file.source ?? file.target), targetPath = `./${file.target}`, force = file.force ?? !1), (0, import_fs16.existsSync)(templatePath) && (force || (0, import_fs16.existsSync)(targetPath)) && (await (0, import_promises2.mkdir)(import_path18.default.dirname(targetPath), { recursive: !0 }), await (0, import_promises2.copyFile)(templatePath, targetPath));
3700
+ typeof file == "string" ? (templatePath = getTemplatePath(file), targetPath = `./${file}`) : (templatePath = file.sourcePath ?? getTemplatePath(file.source ?? file.target), targetPath = `./${file.target}`, force = file.force ?? !1), (0, import_fs16.existsSync)(templatePath) && (force || (0, import_fs16.existsSync)(targetPath)) && (await (0, import_promises2.mkdir)(import_path19.default.dirname(targetPath), { recursive: !0 }), await (0, import_promises2.copyFile)(templatePath, targetPath));
3650
3701
  })
3651
3702
  );
3652
3703
  }, overlayFileCopy = (overlayDir, sourceFilename, targetFilename) => ({
@@ -3709,16 +3760,18 @@ async function up() {
3709
3760
  await copyTemplateFiles([
3710
3761
  ...sharedFiles,
3711
3762
  { ...overlayFileCopy(overlayDirName, npmrcTemplateFilename, ".npmrc"), force: !0 }
3712
- ]), await updateManifestCompatibility(), await updatePackageDependencies(templateDeps), shouldCleanNpmCache && await execCommand("npm cache clean --force"), await execCommand("npm i");
3763
+ ]), await updateManifestCompatibility();
3764
+ let categoriesResponse = await getPluginCategories();
3765
+ generateManifestSchema(categoriesResponse, process.cwd()), await updatePackageDependencies(templateDeps), shouldCleanNpmCache && await execCommand("npm cache clean --force"), await execCommand("npm i");
3713
3766
  }
3714
3767
 
3715
3768
  // src/utils/getVersion.ts
3716
- var import_fs19 = require("fs"), import_path19 = require("path"), UNKNOWN_VERSION = "unknown", CANDIDATES = ["..", "../.."], findVersionInPackageJson = (startDir) => {
3769
+ var import_fs19 = require("fs"), import_path20 = require("path"), UNKNOWN_VERSION = "unknown", CANDIDATES = ["..", "../.."], findVersionInPackageJson = (startDir) => {
3717
3770
  for (let rel of CANDIDATES) {
3718
- let path24 = (0, import_path19.resolve)(startDir, rel, "package.json");
3719
- if ((0, import_fs19.existsSync)(path24))
3771
+ let path26 = (0, import_path20.resolve)(startDir, rel, "package.json");
3772
+ if ((0, import_fs19.existsSync)(path26))
3720
3773
  try {
3721
- let pkg = JSON.parse((0, import_fs19.readFileSync)(path24, "utf-8"));
3774
+ let pkg = JSON.parse((0, import_fs19.readFileSync)(path26, "utf-8"));
3722
3775
  if (typeof pkg.version == "string") return pkg.version;
3723
3776
  } catch {
3724
3777
  }
@@ -3730,10 +3783,10 @@ var import_fs19 = require("fs"), import_path19 = require("path"), UNKNOWN_VERSIO
3730
3783
  init_verbose();
3731
3784
  init_withErrorHandling();
3732
3785
  async function main() {
3733
- let program = new import_commander2.Command(), version = getVersion();
3786
+ let program = new import_commander3.Command(), version = getVersion();
3734
3787
  shouldRunUpdateCheck(process.argv.slice(2)) && await checkUpdate(version), program.name(CLI_NAME2).description(CLI_DESCRIPTION2).version(version).option("--verbose", "enable verbose output"), CLI_HELP_TEXT2 && program.addHelpText("before", CLI_HELP_TEXT2), program.hook("preAction", (thisCommand) => {
3735
3788
  setVerboseEnabled(!!thisCommand.opts().verbose);
3736
- }), program.command("create").description("create your app").action(withErrorHandling(create)), program.command("up").description("update plugin from old template to latest version").action(withErrorHandling(up)), program.command("build").description("build your app").action(withErrorHandling(build)), program.command("debug").description(
3789
+ }), program.command("create").description("create your app").action(withErrorHandling(create)), program.command("up").description("update plugin from old template to latest version").action(withErrorHandling(up)), program.command("build").description("build your app").action(withErrorHandling(build)), program.command("build-docs").description("build diplodoc docs").action(withErrorHandling(buildDocs2)), program.command("debug").description(
3737
3790
  "start a tunnel to connect your local code with the app running in the development environment"
3738
3791
  ).option("--no-lint", "skip lint validation").action((options) => withErrorHandling(debug)(options)), program.command("lint").description("run TypeScript and ESLint checks").action(withErrorHandling(lint)), registerDistributionCommands2(program), await program.parseAsync(), process.exit(typeof process.exitCode == "number" ? process.exitCode : 0);
3739
3792
  }