@weavix/cli 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/build/index.js +1641 -713
  2. package/build/templates/{_shared/src/styles-360.scss → _external/src/styles.scss} +2 -3
  3. package/build/templates/{_shared/src/styles-gravity.scss → _internal/src/styles.scss} +3 -2
  4. package/build/templates/_internal/src/themes/yandex-cloud/_dark-hc.scss +328 -0
  5. package/build/templates/_internal/src/themes/yandex-cloud/_dark.scss +329 -0
  6. package/build/templates/_internal/src/themes/yandex-cloud/_light-hc.scss +321 -0
  7. package/build/templates/_internal/src/themes/yandex-cloud/_light.scss +323 -0
  8. package/build/templates/_internal/src/themes/yandex-cloud.scss +168 -0
  9. package/build/templates/_shared/manifest.schema.json +183 -3
  10. package/build/templates/_shared/package.json +64 -65
  11. package/build/templates/_shared/src/main.tsx +1 -5
  12. package/build/templates/_shared/src/themes/yandex-360/_dark-hc.scss +296 -0
  13. package/build/templates/_shared/src/themes/yandex-360/_dark.scss +297 -0
  14. package/build/templates/_shared/src/themes/yandex-360/_light-hc.scss +289 -0
  15. package/build/templates/_shared/src/themes/yandex-360/_light.scss +291 -0
  16. package/build/templates/_shared/src/themes/yandex-360.scss +197 -0
  17. package/build/templates/_shared/src/themes/ys-text.scss +79 -0
  18. package/build/templates/_shared/vite.config.ts +2 -0
  19. package/build/templates/attachment.viewer.action/index.html +1 -1
  20. package/build/templates/attachment.viewer.action/src/App.tsx +13 -19
  21. package/build/templates/board.tab/index.html +14 -0
  22. package/build/templates/board.tab/src/App.tsx +27 -0
  23. package/build/templates/goal.action/index.html +1 -1
  24. package/build/templates/goal.action/src/App.tsx +4 -16
  25. package/build/templates/goal.block/index.html +14 -0
  26. package/build/templates/goal.block/src/App.tsx +27 -0
  27. package/build/templates/goal.tab/index.html +14 -0
  28. package/build/templates/goal.tab/src/App.tsx +27 -0
  29. package/build/templates/issue.action/index.html +1 -1
  30. package/build/templates/issue.action/src/App.tsx +3 -12
  31. package/build/templates/issue.block/index.html +1 -1
  32. package/build/templates/issue.block/src/App.tsx +9 -18
  33. package/build/templates/issue.comment.action/src/App.tsx +2 -8
  34. package/build/templates/issue.tab/src/App.tsx +2 -11
  35. package/build/templates/portfolio.action/index.html +1 -1
  36. package/build/templates/portfolio.action/src/App.tsx +4 -21
  37. package/build/templates/portfolio.block/index.html +14 -0
  38. package/build/templates/portfolio.block/src/App.tsx +27 -0
  39. package/build/templates/portfolio.tab/index.html +14 -0
  40. package/build/templates/portfolio.tab/src/App.tsx +27 -0
  41. package/build/templates/project.action/index.html +1 -1
  42. package/build/templates/project.action/src/App.tsx +4 -21
  43. package/build/templates/project.block/index.html +14 -0
  44. package/build/templates/project.block/src/App.tsx +27 -0
  45. package/build/templates/project.tab/index.html +14 -0
  46. package/build/templates/project.tab/src/App.tsx +27 -0
  47. package/build/templates/trigger.action/index.html +1 -1
  48. package/package.json +2 -1
package/build/index.js CHANGED
@@ -26,6 +26,13 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
26
26
  mod
27
27
  )), __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: !0 }), mod);
28
28
 
29
+ // src/distribution/flag.ts
30
+ var init_flag = __esm({
31
+ "src/distribution/flag.ts"() {
32
+ "use strict";
33
+ }
34
+ });
35
+
29
36
  // src/distributions/external/meta.ts
30
37
  var meta_exports = {};
31
38
  __export(meta_exports, {
@@ -40,6 +47,26 @@ var CLI_NAME, CLI_DESCRIPTION, CLI_HELP_TEXT, init_meta = __esm({
40
47
  }
41
48
  });
42
49
 
50
+ // src/distribution/meta.ts
51
+ var impl, CLI_NAME2, CLI_DESCRIPTION2, CLI_HELP_TEXT2, init_meta2 = __esm({
52
+ "src/distribution/meta.ts"() {
53
+ "use strict";
54
+ init_flag();
55
+ impl = (init_meta(), __toCommonJS(meta_exports)), { CLI_NAME: CLI_NAME2, CLI_DESCRIPTION: CLI_DESCRIPTION2, CLI_HELP_TEXT: CLI_HELP_TEXT2 } = impl;
56
+ }
57
+ });
58
+
59
+ // src/commands/submit/options.ts
60
+ var import_commander, skipChecksOption, init_options = __esm({
61
+ "src/commands/submit/options.ts"() {
62
+ "use strict";
63
+ import_commander = require("commander"), skipChecksOption = new import_commander.Option(
64
+ "--skip-checks",
65
+ "skip pre-submit validation (manifest, assets, lint, typecheck, tests, audit)"
66
+ );
67
+ }
68
+ });
69
+
43
70
  // src/utils/verbose.ts
44
71
  function setVerboseEnabled(value) {
45
72
  verboseEnabled = value;
@@ -47,10 +74,14 @@ function setVerboseEnabled(value) {
47
74
  function isVerboseEnabled() {
48
75
  return verboseEnabled;
49
76
  }
50
- var verboseEnabled, init_verbose = __esm({
77
+ function writeVerboseArtifact(relativePath, content) {
78
+ let targetPath = import_path.default.resolve(".tracker-cli-debug", relativePath);
79
+ return import_fs.default.mkdirSync(import_path.default.dirname(targetPath), { recursive: !0 }), import_fs.default.writeFileSync(targetPath, content), targetPath;
80
+ }
81
+ var import_fs, import_path, verboseEnabled, init_verbose = __esm({
51
82
  "src/utils/verbose.ts"() {
52
83
  "use strict";
53
- verboseEnabled = !1;
84
+ import_fs = __toESM(require("fs")), import_path = __toESM(require("path")), verboseEnabled = !1;
54
85
  }
55
86
  });
56
87
 
@@ -112,25 +143,25 @@ function getConfigPath() {
112
143
  function readConfig() {
113
144
  if (cached !== void 0)
114
145
  return cached;
115
- if (!(0, import_fs.existsSync)(CONFIG_FILE))
146
+ if (!(0, import_fs2.existsSync)(CONFIG_FILE))
116
147
  return cached = null, cached;
117
148
  try {
118
- cached = JSON.parse((0, import_fs.readFileSync)(CONFIG_FILE, "utf-8"));
149
+ cached = JSON.parse((0, import_fs2.readFileSync)(CONFIG_FILE, "utf-8"));
119
150
  } catch {
120
151
  cached = null;
121
152
  }
122
153
  return cached;
123
154
  }
124
155
  function writeConfig(config) {
125
- (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;
156
+ (0, import_fs2.existsSync)(CONFIG_DIR) || (0, import_fs2.mkdirSync)(CONFIG_DIR, { recursive: !0, mode: 448 }), (0, import_fs2.writeFileSync)(CONFIG_FILE, JSON.stringify(config, null, 2), { mode: 384 }), cached = config;
126
157
  }
127
158
  function clearConfig() {
128
- (0, import_fs.existsSync)(CONFIG_FILE) && (0, import_fs.rmSync)(CONFIG_FILE), cached = null;
159
+ (0, import_fs2.existsSync)(CONFIG_FILE) && (0, import_fs2.rmSync)(CONFIG_FILE), cached = null;
129
160
  }
130
- var import_fs, os, import_path, CONFIG_DIR, CONFIG_FILE, cached, init_manager = __esm({
161
+ var import_fs2, os, import_path2, CONFIG_DIR, CONFIG_FILE, cached, init_manager = __esm({
131
162
  "src/core/cliConfig/manager.ts"() {
132
163
  "use strict";
133
- import_fs = require("fs"), os = __toESM(require("os")), import_path = __toESM(require("path")), CONFIG_DIR = import_path.default.join(os.homedir(), ".tracker-cli"), CONFIG_FILE = import_path.default.join(CONFIG_DIR, "config.json");
164
+ import_fs2 = require("fs"), os = __toESM(require("os")), import_path2 = __toESM(require("path")), CONFIG_DIR = import_path2.default.join(os.homedir(), ".tracker-cli"), CONFIG_FILE = import_path2.default.join(CONFIG_DIR, "config.json");
134
165
  }
135
166
  });
136
167
 
@@ -197,19 +228,1446 @@ var import_prompts, init_registerCommand = __esm({
197
228
  }
198
229
  });
199
230
 
231
+ // src/utils/withErrorHandling.ts
232
+ function withErrorHandling(fn) {
233
+ return async (...args) => {
234
+ try {
235
+ await fn(...args);
236
+ } catch (error2) {
237
+ error2 instanceof Error && error2.name === "ExitPromptError" && process.exit(0), logger_default.error(error2), process.exit(1);
238
+ }
239
+ };
240
+ }
241
+ var init_withErrorHandling = __esm({
242
+ "src/utils/withErrorHandling.ts"() {
243
+ "use strict";
244
+ init_logger();
245
+ }
246
+ });
247
+
248
+ // src/core/pluginState/pluginStateManager.ts
249
+ var import_fs3, import_promises, STATE_FILE, load, save, update, pluginStateManager, init_pluginStateManager = __esm({
250
+ "src/core/pluginState/pluginStateManager.ts"() {
251
+ "use strict";
252
+ import_fs3 = require("fs"), import_promises = require("fs/promises"), STATE_FILE = ".tracker-plugin", load = async () => {
253
+ if (!(0, import_fs3.existsSync)(STATE_FILE))
254
+ return {};
255
+ try {
256
+ let content = await (0, import_promises.readFile)(STATE_FILE, "utf8");
257
+ return JSON.parse(content);
258
+ } catch {
259
+ return {};
260
+ }
261
+ }, save = async (state) => {
262
+ try {
263
+ let content = JSON.stringify(state, null, 4);
264
+ await (0, import_promises.writeFile)(STATE_FILE, content, "utf8");
265
+ } catch (error2) {
266
+ throw error2 instanceof Error ? new Error(`Error saving ${STATE_FILE}: ${error2.message}`) : new Error(`Error saving ${STATE_FILE}`);
267
+ }
268
+ }, update = async (updates) => {
269
+ let updated = { ...await load(), ...updates };
270
+ return await save(updated), updated;
271
+ }, pluginStateManager = {
272
+ load,
273
+ save,
274
+ update
275
+ };
276
+ }
277
+ });
278
+
279
+ // src/api/utils.ts
280
+ function getIssueStatusLabel(issue) {
281
+ let { key: statusKey, display: statusDisplay } = issue.status;
282
+ return statusKey === "closed" && issue.resolution?.display ? issue.resolution.display : statusDisplay ?? statusKey;
283
+ }
284
+ function getIssueStatusCategory(issue) {
285
+ let statusKey = issue.status.key, resolutionKey = issue.resolution?.key;
286
+ if (statusKey === "closed")
287
+ return resolutionKey === "agreed" ? "approved" : resolutionKey === "rejected" || resolutionKey === "declined" ? "rejected" : "neutral";
288
+ switch (statusKey) {
289
+ case "waitingForApprove":
290
+ case "inProgress":
291
+ return "pending";
292
+ case "resultAcceptance":
293
+ return "acceptance";
294
+ case "testing":
295
+ return "testing";
296
+ case "need_info":
297
+ return "need_info";
298
+ default:
299
+ return "neutral";
300
+ }
301
+ }
302
+ var init_utils = __esm({
303
+ "src/api/utils.ts"() {
304
+ "use strict";
305
+ }
306
+ });
307
+
308
+ // src/utils/pluginDisplay.ts
309
+ function showTrackerPluginList(issues) {
310
+ if (!issues || issues.length === 0) {
311
+ console.info(import_picocolors2.default.dim(" No plugins found")), logger_default.newLine();
312
+ return;
313
+ }
314
+ printHeader(`\u{1F4CB} Your Plugins \xB7 ${issues.length}`), logger_default.newLine(), issues.forEach((issue) => {
315
+ let slugMatch = issue.summary.match(/^Plugin:\s*(.+)$/), slug = slugMatch ? import_picocolors2.default.magenta(slugMatch[1].trim()) : import_picocolors2.default.dim(issue.summary), statusBadge = getTrackerIssueBadge(issue);
316
+ console.info(
317
+ ` ${slug} ${import_picocolors2.default.dim("\xB7")} ${statusBadge} ${import_picocolors2.default.dim("\xB7")} ${import_picocolors2.default.dim(issue.key)}`
318
+ ), logger_default.newLine();
319
+ });
320
+ }
321
+ function showTrackerPluginInfo(issue) {
322
+ printHeader("\u{1F4E6} Plugin"), logger_default.newLine(), printField("Issue key", import_picocolors2.default.cyan(issue.key)), printField("Status", getTrackerIssueBadge(issue)), printField("Summary", import_picocolors2.default.white(issue.summary)), issue.createdAt && printCreated(issue.createdAt), issue.updatedAt && printUpdated(issue.updatedAt);
323
+ }
324
+ var import_picocolors2, printHeader, getTrackerIssueBadge, formatDate, printField, printCreated, printUpdated, init_pluginDisplay = __esm({
325
+ "src/utils/pluginDisplay.ts"() {
326
+ "use strict";
327
+ import_picocolors2 = __toESM(require("picocolors"));
328
+ init_utils();
329
+ init_logger();
330
+ printHeader = (title) => {
331
+ console.info(import_picocolors2.default.bold(import_picocolors2.default.white(title)));
332
+ }, getTrackerIssueBadge = (issue) => {
333
+ let label = getIssueStatusLabel(issue);
334
+ switch (getIssueStatusCategory(issue)) {
335
+ case "approved":
336
+ return import_picocolors2.default.black(import_picocolors2.default.bgGreen(` ${label} `));
337
+ case "rejected":
338
+ return import_picocolors2.default.white(import_picocolors2.default.bgRed(` ${label} `));
339
+ case "pending":
340
+ return import_picocolors2.default.black(import_picocolors2.default.bgYellow(` ${label} `));
341
+ case "acceptance":
342
+ return import_picocolors2.default.black(import_picocolors2.default.bgCyan(` ${label} `));
343
+ case "testing":
344
+ return import_picocolors2.default.black(import_picocolors2.default.bgMagenta(` ${label} `));
345
+ case "need_info":
346
+ return import_picocolors2.default.black(import_picocolors2.default.bgBlue(` ${label} `));
347
+ default:
348
+ return import_picocolors2.default.black(import_picocolors2.default.bgWhite(` ${label} `));
349
+ }
350
+ }, formatDate = (dateString) => dateString ? new Date(dateString).toLocaleString("ru-RU", {
351
+ year: "numeric",
352
+ month: "2-digit",
353
+ day: "2-digit",
354
+ hour: "2-digit",
355
+ minute: "2-digit"
356
+ }) : "-", printField = (label, value, minWidth = 12) => {
357
+ console.info(` ${import_picocolors2.default.dim(label.padEnd(minWidth))} ${value}`);
358
+ }, printCreated = (createdAt) => {
359
+ printField("Created", import_picocolors2.default.white(formatDate(createdAt)));
360
+ }, printUpdated = (updatedAt) => {
361
+ printField("Updated", import_picocolors2.default.white(formatDate(updatedAt)));
362
+ };
363
+ }
364
+ });
365
+
366
+ // src/distributions/external/authManager.ts
367
+ var fs2, os2, path3, authDir, authFile, getData, getToken, saveAuthData, removeAuthData, externalAuthManager, init_authManager = __esm({
368
+ "src/distributions/external/authManager.ts"() {
369
+ "use strict";
370
+ fs2 = __toESM(require("fs")), os2 = __toESM(require("os")), path3 = __toESM(require("path")), authDir = path3.join(os2.homedir(), ".weavix"), authFile = path3.join(authDir, "auth.json"), getData = () => {
371
+ try {
372
+ if (!fs2.existsSync(authFile))
373
+ return null;
374
+ let data = fs2.readFileSync(authFile, "utf-8");
375
+ return JSON.parse(data);
376
+ } catch {
377
+ return null;
378
+ }
379
+ }, getToken = () => getData()?.token ?? null, saveAuthData = (token) => {
380
+ let authData = { token };
381
+ fs2.existsSync(authDir) || fs2.mkdirSync(authDir, { recursive: !0, mode: 448 }), fs2.writeFileSync(authFile, JSON.stringify(authData, null, 2), {
382
+ mode: 384
383
+ });
384
+ }, removeAuthData = () => {
385
+ fs2.existsSync(authFile) && fs2.unlinkSync(authFile);
386
+ }, externalAuthManager = {
387
+ get token() {
388
+ return getToken();
389
+ },
390
+ get data() {
391
+ return getData();
392
+ },
393
+ saveAuthData,
394
+ removeAuthData
395
+ };
396
+ }
397
+ });
398
+
399
+ // src/distributions/external/trackerApiRequest.ts
400
+ function buildQueryString(queryParams) {
401
+ if (!queryParams || Object.keys(queryParams).length === 0)
402
+ return "";
403
+ let params = new URLSearchParams();
404
+ return Object.entries(queryParams).forEach(([key, value]) => {
405
+ params.append(key, String(value));
406
+ }), `?${params.toString()}`;
407
+ }
408
+ async function parseResponse(response) {
409
+ 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();
410
+ }
411
+ async function externalTrackerApiRequest(endpoint, options = {}) {
412
+ let { method = "GET", body, headers = {}, formData, queryParams } = options, token = externalAuthManager.token;
413
+ if (!token)
414
+ throw new Error(`Not authenticated. Run "${CLI_NAME} login" first.`);
415
+ let requestHeaders = {
416
+ Authorization: `OAuth ${token}`,
417
+ "X-Org-ID": ORG_ID,
418
+ Accept: "application/json",
419
+ ...headers
420
+ }, requestBody;
421
+ if (formData) {
422
+ let formHeaders = formData.getHeaders?.();
423
+ Object.assign(requestHeaders, formHeaders), requestBody = formData;
424
+ } else body && method !== "GET" && (requestHeaders["Content-Type"] = "application/json", requestBody = JSON.stringify(body));
425
+ let queryString = buildQueryString(queryParams), url = `${TRACKER_BASE_URL}${endpoint}${queryString}`, response = await (0, import_node_fetch.default)(url, {
426
+ method,
427
+ headers: requestHeaders,
428
+ body: requestBody
429
+ });
430
+ if (!response.ok) {
431
+ let errorText = await response.text(), errorMessage = `Tracker API error ${response.status}: ${errorText}`;
432
+ try {
433
+ let errorJson = JSON.parse(errorText);
434
+ errorJson.message && (errorMessage = `Tracker API error ${response.status}: ${errorJson.message}`);
435
+ } catch {
436
+ }
437
+ throw new Error(errorMessage);
438
+ }
439
+ return parseResponse(response);
440
+ }
441
+ var import_node_fetch, TRACKER_BASE_URL, ORG_ID, init_trackerApiRequest = __esm({
442
+ "src/distributions/external/trackerApiRequest.ts"() {
443
+ "use strict";
444
+ import_node_fetch = __toESM(require("node-fetch"));
445
+ init_authManager();
446
+ init_meta();
447
+ TRACKER_BASE_URL = "https://api.tracker.yandex.net/v3", ORG_ID = "8470884";
448
+ }
449
+ });
450
+
451
+ // src/distributions/external/tracker.ts
452
+ function buildIssueSummary(slug) {
453
+ return `Plugin: ${slug}`;
454
+ }
455
+ function buildIssueDescription(params) {
456
+ let { pluginId, slug, version, manifestJson } = params;
457
+ return [
458
+ `**Plugin UUID:** ${pluginId}`,
459
+ `**Slug:** ${slug}`,
460
+ `**Version:** ${version}`,
461
+ "",
462
+ "**Manifest:**",
463
+ "```json",
464
+ manifestJson,
465
+ "```"
466
+ ].join(`
467
+ `);
468
+ }
469
+ async function createPluginIssue(params) {
470
+ let { slug, pluginId, version, manifestJson } = params, body = {
471
+ queue: PLUGINMOD_QUEUE,
472
+ summary: buildIssueSummary(slug),
473
+ description: buildIssueDescription({ pluginId, slug, version, manifestJson }),
474
+ tags: ["tracker-plugin"]
475
+ };
476
+ return externalTrackerApiRequest("/issues", {
477
+ method: "POST",
478
+ body
479
+ });
480
+ }
481
+ async function updatePluginIssue(issueKey, params) {
482
+ return externalTrackerApiRequest(`/issues/${issueKey}`, {
483
+ method: "PATCH",
484
+ body: params
485
+ });
486
+ }
487
+ async function attachFileToIssue(issueKey, fileBuffer, fileName) {
488
+ let formData = new import_form_data.default();
489
+ return formData.append("file", fileBuffer, {
490
+ filename: fileName,
491
+ contentType: "application/zip"
492
+ }), externalTrackerApiRequest(`/issues/${issueKey}/attachments`, {
493
+ method: "POST",
494
+ formData
495
+ });
496
+ }
497
+ async function getIssueTransitions(issueKey) {
498
+ return externalTrackerApiRequest(`/issues/${issueKey}/transitions`, {
499
+ method: "GET"
500
+ });
501
+ }
502
+ async function executeIssueTransition(issueKey, transitionId) {
503
+ await externalTrackerApiRequest(
504
+ `/issues/${issueKey}/transitions/${transitionId}/_execute`,
505
+ {
506
+ method: "POST",
507
+ body: {}
508
+ }
509
+ );
510
+ }
511
+ async function getIssue(issueKey) {
512
+ return externalTrackerApiRequest(`/issues/${issueKey}`, {
513
+ method: "GET"
514
+ });
515
+ }
516
+ async function addIssueComment(issueKey, text) {
517
+ await externalTrackerApiRequest(`/issues/${issueKey}/comments`, {
518
+ method: "POST",
519
+ body: { text }
520
+ });
521
+ }
522
+ async function getMyPluginIssues() {
523
+ return externalTrackerApiRequest("/issues/_search", {
524
+ method: "POST",
525
+ body: {
526
+ filter: {
527
+ queue: "PLUGINMOD",
528
+ createdBy: "me()"
529
+ }
530
+ }
531
+ });
532
+ }
533
+ var import_form_data, PLUGINMOD_QUEUE, init_tracker = __esm({
534
+ "src/distributions/external/tracker.ts"() {
535
+ "use strict";
536
+ import_form_data = __toESM(require("form-data"));
537
+ init_trackerApiRequest();
538
+ PLUGINMOD_QUEUE = "PLUGINMOD";
539
+ }
540
+ });
541
+
542
+ // src/distributions/external/info.ts
543
+ async function infoExternal(issueKey) {
544
+ let targetIssueKey = issueKey;
545
+ if (targetIssueKey || (targetIssueKey = (await pluginStateManager.load()).trackerIssueKey), !targetIssueKey) {
546
+ logger_default.warning(
547
+ `No issue key provided and plugin has not been submitted yet. Run "${CLI_NAME} submit" first.`
548
+ ), logger_default.suggest(`${CLI_NAME} submit`);
549
+ return;
550
+ }
551
+ logger_default.info(`\u23F3 Fetching plugin info for ${targetIssueKey}...`);
552
+ try {
553
+ let issue = await getIssue(targetIssueKey);
554
+ showTrackerPluginInfo(issue);
555
+ } catch (error2) {
556
+ throw logger_default.error(`Failed to fetch plugin info for ${targetIssueKey}`), error2;
557
+ }
558
+ }
559
+ var init_info = __esm({
560
+ "src/distributions/external/info.ts"() {
561
+ "use strict";
562
+ init_pluginStateManager();
563
+ init_logger();
564
+ init_pluginDisplay();
565
+ init_meta();
566
+ init_tracker();
567
+ }
568
+ });
569
+
570
+ // src/distributions/external/list.ts
571
+ async function listExternal() {
572
+ logger_default.info("\u23F3 Fetching my plugins from Tracker...");
573
+ try {
574
+ let issues = await getMyPluginIssues();
575
+ showTrackerPluginList(issues);
576
+ } catch (error2) {
577
+ throw logger_default.error("Failed to fetch plugins list"), error2;
578
+ }
579
+ }
580
+ var init_list = __esm({
581
+ "src/distributions/external/list.ts"() {
582
+ "use strict";
583
+ init_logger();
584
+ init_pluginDisplay();
585
+ init_tracker();
586
+ }
587
+ });
588
+
589
+ // src/distributions/external/login.ts
590
+ async function loginExternal() {
591
+ console.info(
592
+ import_picocolors3.default.dim(
593
+ "To get an OAuth token for Yandex Tracker, please contact Tracker support and request one."
594
+ )
595
+ ), console.info("");
596
+ let trimmed = (await (0, import_prompts2.input)({
597
+ message: "Enter your OAuth token:",
598
+ required: !0
599
+ })).trim();
600
+ externalAuthManager.saveAuthData(trimmed), logger_default.success("OAuth token saved successfully."), logger_default.info('You can now use "weavix submit" to submit your plugin for review.');
601
+ }
602
+ function logoutExternal() {
603
+ if (!externalAuthManager.data) {
604
+ logger_default.warning("You are not logged in.");
605
+ return;
606
+ }
607
+ externalAuthManager.removeAuthData(), logger_default.success("Successfully logged out.");
608
+ }
609
+ var import_prompts2, import_picocolors3, init_login = __esm({
610
+ "src/distributions/external/login.ts"() {
611
+ "use strict";
612
+ import_prompts2 = require("@inquirer/prompts"), import_picocolors3 = __toESM(require("picocolors"));
613
+ init_logger();
614
+ init_authManager();
615
+ }
616
+ });
617
+
618
+ // src/utils/execCommand.ts
619
+ var import_execa, execCommand, init_execCommand = __esm({
620
+ "src/utils/execCommand.ts"() {
621
+ "use strict";
622
+ import_execa = require("execa"), execCommand = async (command, cwd = process.cwd(), env) => {
623
+ await (0, import_execa.execa)(command, {
624
+ cwd,
625
+ shell: !0,
626
+ stdio: "inherit",
627
+ env: env ? { ...process.env, ...env } : void 0
628
+ });
629
+ };
630
+ }
631
+ });
632
+
633
+ // src/commands/constants/templateCommands.ts
634
+ var pluginCmd, init_templateCommands = __esm({
635
+ "src/commands/constants/templateCommands.ts"() {
636
+ "use strict";
637
+ pluginCmd = {
638
+ install: "npm install",
639
+ build: "npm run build",
640
+ dev: "npm run dev",
641
+ lint: "npm run lint",
642
+ typecheck: "npm run typecheck",
643
+ test: "npm test",
644
+ audit: "npm audit --audit-level=critical"
645
+ };
646
+ }
647
+ });
648
+
649
+ // src/commands/build.ts
650
+ var build, init_build = __esm({
651
+ "src/commands/build.ts"() {
652
+ "use strict";
653
+ init_execCommand();
654
+ init_logger();
655
+ init_templateCommands();
656
+ build = async ({ environment = "production" } = {}) => {
657
+ logger_default.info("\u{1F528} Building project..."), await execCommand(pluginCmd.install), await execCommand(
658
+ pluginCmd.build,
659
+ process.cwd(),
660
+ environment ? { VITE_DEPLOY_ENV: environment } : void 0
661
+ );
662
+ };
663
+ }
664
+ });
665
+
666
+ // src/distributions/external/manifestPermissionsSchema.ts
667
+ var manifestPermissionsSchema_exports = {};
668
+ __export(manifestPermissionsSchema_exports, {
669
+ permissionsSchemaExtensions: () => permissionsSchemaExtensions
670
+ });
671
+ var permissionsSchemaExtensions, init_manifestPermissionsSchema = __esm({
672
+ "src/distributions/external/manifestPermissionsSchema.ts"() {
673
+ "use strict";
674
+ permissionsSchemaExtensions = {};
675
+ }
676
+ });
677
+
678
+ // src/distribution/manifestPermissionsSchema.ts
679
+ var impl2, permissionsSchemaExtensions2, init_manifestPermissionsSchema2 = __esm({
680
+ "src/distribution/manifestPermissionsSchema.ts"() {
681
+ "use strict";
682
+ init_flag();
683
+ impl2 = (init_manifestPermissionsSchema(), __toCommonJS(manifestPermissionsSchema_exports)), { permissionsSchemaExtensions: permissionsSchemaExtensions2 } = impl2;
684
+ }
685
+ });
686
+
687
+ // src/core/manifest/formatValidationErrors.ts
688
+ var priorityOrder, errorMessages, getPriority, formatValidationErrors, init_formatValidationErrors = __esm({
689
+ "src/core/manifest/formatValidationErrors.ts"() {
690
+ "use strict";
691
+ priorityOrder = [
692
+ "required",
693
+ "type",
694
+ "minLength",
695
+ "format",
696
+ "pattern",
697
+ "enum",
698
+ "additionalProperties",
699
+ "uniqueItems"
700
+ ], errorMessages = {
701
+ required: (params) => `missing required property '${params.missingProperty}'`,
702
+ type: (params) => `must be ${params.type}`,
703
+ enum: (params) => `must be one of [${params.allowedValues.join(", ")}]`,
704
+ pattern: (params) => `must match pattern ${params.pattern}`,
705
+ format: (params) => `must be a valid ${params.format}`,
706
+ minLength: () => "must not be empty",
707
+ additionalProperties: (params) => `unexpected property '${params.additionalProperty}'`,
708
+ uniqueItems: () => "must contain unique items"
709
+ }, getPriority = (keyword) => {
710
+ let index = priorityOrder.indexOf(keyword);
711
+ return index === -1 ? priorityOrder.length : index;
712
+ }, formatValidationErrors = (errors) => {
713
+ let errorsByPath = {};
714
+ for (let error2 of errors) {
715
+ let path18 = error2.instancePath || "root";
716
+ errorsByPath[path18] || (errorsByPath[path18] = []), errorsByPath[path18].push(error2);
717
+ }
718
+ return Object.entries(errorsByPath).map(([path18, pathErrors]) => {
719
+ let error2 = [...pathErrors].sort(
720
+ (a, b) => getPriority(a.keyword) - getPriority(b.keyword)
721
+ )[0], formatter = errorMessages[error2.keyword], message = formatter ? formatter(error2.params) : error2.message;
722
+ return ` - ${path18}: ${message}`;
723
+ }).join(`
724
+ `);
725
+ };
726
+ }
727
+ });
728
+
729
+ // src/core/manifest/manifest.schema.json
730
+ var manifest_schema_default, init_manifest_schema = __esm({
731
+ "src/core/manifest/manifest.schema.json"() {
732
+ manifest_schema_default = {
733
+ $schema: "http://json-schema.org/draft-07/schema#",
734
+ title: "Manifest",
735
+ description: "Schema for validating plugin manifest",
736
+ type: "object",
737
+ required: [
738
+ "slug",
739
+ "version",
740
+ "permissions",
741
+ "name",
742
+ "description",
743
+ "support"
744
+ ],
745
+ properties: {
746
+ $schema: {
747
+ type: "string"
748
+ },
749
+ id: {
750
+ type: "string",
751
+ description: "Unique identifier for the plugin ()",
752
+ minLength: 3,
753
+ maxLength: 63,
754
+ pattern: "^[a-z0-9-]+$"
755
+ },
756
+ manifest_version: {
757
+ type: "number",
758
+ description: "Manifest format version",
759
+ minimum: 1
760
+ },
761
+ supported_services: {
762
+ type: "array",
763
+ description: "Supported services for this plugin",
764
+ items: {
765
+ type: "string",
766
+ enum: [
767
+ "tracker"
768
+ ]
769
+ },
770
+ minItems: 1,
771
+ uniqueItems: !0
772
+ },
773
+ slug: {
774
+ type: "string",
775
+ description: "Unique identifier for the plugin (lowercase letters, numbers, hyphen)",
776
+ minLength: 3,
777
+ maxLength: 63,
778
+ pattern: "^[a-z0-9-]+$"
779
+ },
780
+ version: {
781
+ type: "string",
782
+ description: "Version of the plugin (semver format required)",
783
+ minLength: 1,
784
+ pattern: "^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9.-]+)?(\\+[a-zA-Z0-9.-]+)?$"
785
+ },
786
+ name: {
787
+ type: "object",
788
+ description: "Localized plugin name",
789
+ required: [
790
+ "ru",
791
+ "en"
792
+ ],
793
+ properties: {
794
+ ru: {
795
+ type: "string",
796
+ description: "Russian name",
797
+ minLength: 1,
798
+ maxLength: 30
799
+ },
800
+ en: {
801
+ type: "string",
802
+ description: "English name",
803
+ minLength: 1,
804
+ maxLength: 30
805
+ }
806
+ },
807
+ additionalProperties: !1
808
+ },
809
+ description: {
810
+ type: "object",
811
+ description: "Localized plugin description",
812
+ required: [
813
+ "ru",
814
+ "en"
815
+ ],
816
+ properties: {
817
+ ru: {
818
+ type: "string",
819
+ description: "Russian description",
820
+ minLength: 1,
821
+ maxLength: 255
822
+ },
823
+ en: {
824
+ type: "string",
825
+ description: "English description",
826
+ minLength: 1,
827
+ maxLength: 255
828
+ }
829
+ },
830
+ additionalProperties: !1
831
+ },
832
+ support: {
833
+ type: "array",
834
+ description: "Support contact information",
835
+ items: {
836
+ type: "object",
837
+ required: [
838
+ "type",
839
+ "value"
840
+ ],
841
+ properties: {
842
+ type: {
843
+ type: "string",
844
+ description: "Type of support contact",
845
+ enum: [
846
+ "email"
847
+ ]
848
+ },
849
+ value: {
850
+ type: "string",
851
+ description: "Contact value",
852
+ minLength: 1,
853
+ maxLength: 100
854
+ }
855
+ },
856
+ additionalProperties: !1
857
+ },
858
+ minItems: 1
859
+ },
860
+ homepage: {
861
+ type: "string",
862
+ description: "Homepage URL for the plugin (http or https)",
863
+ pattern: "^https?://",
864
+ maxLength: 1e3
865
+ },
866
+ license: {
867
+ type: "string",
868
+ description: "License identifier (e.g., MIT, Apache-2.0)",
869
+ minLength: 1,
870
+ maxLength: 32
871
+ },
872
+ keywords: {
873
+ type: "array",
874
+ description: "Keywords for plugin discovery",
875
+ items: {
876
+ type: "string",
877
+ minLength: 1,
878
+ maxLength: 30
879
+ },
880
+ uniqueItems: !0
881
+ },
882
+ whatsnew: {
883
+ type: "string",
884
+ description: "What's new in this version",
885
+ minLength: 1,
886
+ maxLength: 300
887
+ },
888
+ externalHost: {
889
+ type: "string",
890
+ description: "External host URL for the plugin (https only)",
891
+ format: "uri",
892
+ pattern: "^https://",
893
+ maxLength: 1e3
894
+ },
895
+ permissions: {
896
+ type: "object",
897
+ description: "Permissions required by the plugin",
898
+ required: [
899
+ "data"
900
+ ],
901
+ properties: {
902
+ data: {
903
+ type: "array",
904
+ description: "Data access permissions",
905
+ items: {
906
+ type: "string",
907
+ enum: [
908
+ "tracker:issues:read",
909
+ "tracker:issues:write",
910
+ "tracker:issuetypes:read",
911
+ "tracker:statuses:read",
912
+ "tracker:queues:read",
913
+ "tracker:fields:read",
914
+ "tracker:entities:read",
915
+ "tracker:attachments:read",
916
+ "tracker:attachments:write",
917
+ "tracker:applications:read",
918
+ "tracker:boards:read",
919
+ "tracker:boards:write",
920
+ "tracker:bulk:read",
921
+ "tracker:bulk:write",
922
+ "tracker:bulkchange:read",
923
+ "tracker:bulkchange:write",
924
+ "tracker:charts:read",
925
+ "tracker:commentTemplates:read",
926
+ "tracker:commentTemplates:write",
927
+ "tracker:components:read",
928
+ "tracker:components:write",
929
+ "tracker:data:read",
930
+ "tracker:departments:read",
931
+ "tracker:entities:write",
932
+ "tracker:externalEventTypes:write",
933
+ "tracker:externalEvents:write",
934
+ "tracker:fields:write",
935
+ "tracker:filterFolders:write",
936
+ "tracker:filters:read",
937
+ "tracker:filters:write",
938
+ "tracker:goals:read",
939
+ "tracker:goals:write",
940
+ "tracker:groups:read",
941
+ "tracker:issueTemplates:read",
942
+ "tracker:issueTemplates:write",
943
+ "tracker:links:read",
944
+ "tracker:linktypes:read",
945
+ "tracker:liveBoards:write",
946
+ "tracker:localFields:read",
947
+ "tracker:maillists:read",
948
+ "tracker:maillists:write",
949
+ "tracker:myself:read",
950
+ "tracker:myself:write",
951
+ "tracker:priorities:read",
952
+ "tracker:queues:write",
953
+ "tracker:reminders:read",
954
+ "tracker:reminders:write",
955
+ "tracker:remotelinks:read",
956
+ "tracker:reports:read",
957
+ "tracker:reports:write",
958
+ "tracker:resolutions:read",
959
+ "tracker:resources:read",
960
+ "tracker:resources:write",
961
+ "tracker:roles:read",
962
+ "tracker:screens:read",
963
+ "tracker:services:read",
964
+ "tracker:sprints:read",
965
+ "tracker:sprints:write",
966
+ "tracker:system:write",
967
+ "tracker:tags:read",
968
+ "tracker:translations:read",
969
+ "tracker:users:read",
970
+ "tracker:users:write",
971
+ "tracker:versions:read",
972
+ "tracker:versions:write",
973
+ "tracker:workflows:read",
974
+ "tracker:workflows:write",
975
+ "tracker:worklog:read",
976
+ "tracker:worklog:write"
977
+ ]
978
+ },
979
+ uniqueItems: !0
980
+ },
981
+ ui: {
982
+ type: "array",
983
+ description: "UI permissions",
984
+ items: {
985
+ type: "string"
986
+ },
987
+ uniqueItems: !0
988
+ },
989
+ device: {
990
+ type: "array",
991
+ description: "Device permissions",
992
+ items: {
993
+ type: "string",
994
+ enum: [
995
+ "clipboard-write"
996
+ ]
997
+ },
998
+ uniqueItems: !0
999
+ },
1000
+ external: {
1001
+ type: "array",
1002
+ description: "External API domains the plugin may call through the platform proxy",
1003
+ items: {
1004
+ $ref: "#/definitions/ExternalDomain"
1005
+ },
1006
+ uniqueItems: !0
1007
+ }
1008
+ },
1009
+ additionalProperties: !1
1010
+ },
1011
+ slots: {
1012
+ type: "object",
1013
+ description: "Configuration for service slots",
1014
+ minProperties: 1,
1015
+ properties: {
1016
+ tracker: {
1017
+ type: "object",
1018
+ description: "Tracker service slots",
1019
+ minProperties: 1,
1020
+ properties: {
1021
+ "issue.action": {
1022
+ type: "array",
1023
+ description: "Issue Action slot configurations",
1024
+ minItems: 1,
1025
+ items: {
1026
+ $ref: "#/definitions/SlotConfig"
1027
+ }
1028
+ },
1029
+ "issue.block": {
1030
+ type: "array",
1031
+ description: "Issue Block slot configurations",
1032
+ minItems: 1,
1033
+ items: {
1034
+ $ref: "#/definitions/SlotConfig"
1035
+ }
1036
+ },
1037
+ "issue.tab": {
1038
+ type: "array",
1039
+ description: "Issue Tab slot configurations",
1040
+ minItems: 1,
1041
+ items: {
1042
+ $ref: "#/definitions/SlotConfig"
1043
+ }
1044
+ },
1045
+ "issue.comment.action": {
1046
+ type: "array",
1047
+ description: "Issue Comment Action slot configurations",
1048
+ minItems: 1,
1049
+ items: {
1050
+ $ref: "#/definitions/SlotConfig"
1051
+ }
1052
+ },
1053
+ navigation: {
1054
+ type: "array",
1055
+ description: "Navigation slot configurations",
1056
+ minItems: 1,
1057
+ items: {
1058
+ $ref: "#/definitions/SlotConfig"
1059
+ }
1060
+ },
1061
+ "trigger.create.action": {
1062
+ type: "array",
1063
+ description: "Trigger Create Action slot configurations",
1064
+ minItems: 1,
1065
+ items: {
1066
+ $ref: "#/definitions/SlotConfig"
1067
+ }
1068
+ },
1069
+ "trigger.edit.action": {
1070
+ type: "array",
1071
+ description: "Trigger Edit Action slot configurations",
1072
+ minItems: 1,
1073
+ items: {
1074
+ $ref: "#/definitions/SlotConfig"
1075
+ }
1076
+ },
1077
+ "project.action": {
1078
+ type: "array",
1079
+ description: "Project Action slot configurations",
1080
+ minItems: 1,
1081
+ items: {
1082
+ $ref: "#/definitions/SlotConfig"
1083
+ }
1084
+ },
1085
+ "project.block": {
1086
+ type: "array",
1087
+ description: "Project Block slot configurations",
1088
+ minItems: 1,
1089
+ items: {
1090
+ $ref: "#/definitions/SlotConfig"
1091
+ }
1092
+ },
1093
+ "project.tab": {
1094
+ type: "array",
1095
+ description: "Project Tab slot configurations",
1096
+ minItems: 1,
1097
+ items: {
1098
+ $ref: "#/definitions/SlotConfig"
1099
+ }
1100
+ },
1101
+ "portfolio.action": {
1102
+ type: "array",
1103
+ description: "Portfolio Action slot configurations",
1104
+ minItems: 1,
1105
+ items: {
1106
+ $ref: "#/definitions/SlotConfig"
1107
+ }
1108
+ },
1109
+ "portfolio.block": {
1110
+ type: "array",
1111
+ description: "Portfolio Block slot configurations",
1112
+ minItems: 1,
1113
+ items: {
1114
+ $ref: "#/definitions/SlotConfig"
1115
+ }
1116
+ },
1117
+ "portfolio.tab": {
1118
+ type: "array",
1119
+ description: "Portfolio Tab slot configurations",
1120
+ minItems: 1,
1121
+ items: {
1122
+ $ref: "#/definitions/SlotConfig"
1123
+ }
1124
+ },
1125
+ "goal.action": {
1126
+ type: "array",
1127
+ description: "Goal Action slot configurations",
1128
+ minItems: 1,
1129
+ items: {
1130
+ $ref: "#/definitions/SlotConfig"
1131
+ }
1132
+ },
1133
+ "goal.block": {
1134
+ type: "array",
1135
+ description: "Goal Block slot configurations",
1136
+ minItems: 1,
1137
+ items: {
1138
+ $ref: "#/definitions/SlotConfig"
1139
+ }
1140
+ },
1141
+ "goal.tab": {
1142
+ type: "array",
1143
+ description: "Goal Tab slot configurations",
1144
+ minItems: 1,
1145
+ items: {
1146
+ $ref: "#/definitions/SlotConfig"
1147
+ }
1148
+ },
1149
+ "attachment.viewer.action": {
1150
+ type: "array",
1151
+ description: "Attachment Viewer Action slot configurations",
1152
+ minItems: 1,
1153
+ items: {
1154
+ $ref: "#/definitions/SlotConfig"
1155
+ }
1156
+ },
1157
+ "board.tab": {
1158
+ type: "array",
1159
+ description: "Board Tab slot configurations",
1160
+ minItems: 1,
1161
+ items: {
1162
+ $ref: "#/definitions/SlotConfig"
1163
+ }
1164
+ },
1165
+ dock: {
1166
+ type: "array",
1167
+ description: "Dock slot configurations",
1168
+ minItems: 1,
1169
+ items: {
1170
+ $ref: "#/definitions/SlotConfig"
1171
+ }
1172
+ }
1173
+ },
1174
+ additionalProperties: !1
1175
+ }
1176
+ },
1177
+ additionalProperties: !1
1178
+ }
1179
+ },
1180
+ additionalProperties: !1,
1181
+ definitions: {
1182
+ ExternalDomain: {
1183
+ type: "object",
1184
+ description: "External API domain declaration with optional authorization config",
1185
+ required: [
1186
+ "domain"
1187
+ ],
1188
+ properties: {
1189
+ domain: {
1190
+ type: "string",
1191
+ description: "Hostname of the external API (no scheme, no path, lowercase)",
1192
+ pattern: "^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)+$",
1193
+ minLength: 1,
1194
+ maxLength: 253
1195
+ },
1196
+ authorization: {
1197
+ $ref: "#/definitions/ExternalAuthorization"
1198
+ },
1199
+ instructions: {
1200
+ type: "object",
1201
+ description: "Localized note shown to the end user when they need to provide a token for this domain (e.g. where to generate the PAT)",
1202
+ required: [
1203
+ "ru",
1204
+ "en"
1205
+ ],
1206
+ properties: {
1207
+ ru: {
1208
+ type: "string",
1209
+ description: "Russian instructions",
1210
+ minLength: 1,
1211
+ maxLength: 500
1212
+ },
1213
+ en: {
1214
+ type: "string",
1215
+ description: "English instructions",
1216
+ minLength: 1,
1217
+ maxLength: 500
1218
+ }
1219
+ },
1220
+ additionalProperties: !1
1221
+ }
1222
+ },
1223
+ additionalProperties: !1
1224
+ },
1225
+ ExternalAuthorization: {
1226
+ type: "object",
1227
+ description: "Authorization config for an external API domain",
1228
+ required: [
1229
+ "type"
1230
+ ],
1231
+ properties: {
1232
+ type: {
1233
+ type: "string",
1234
+ description: "Authorization scheme: oauth (full OAuth flow or manual PAT for an OAuth provider) or token (manual non-OAuth token, e.g. API key)",
1235
+ enum: [
1236
+ "oauth",
1237
+ "token"
1238
+ ]
1239
+ },
1240
+ scopes: {
1241
+ type: "array",
1242
+ description: "Scopes required by this version of the plugin for the domain",
1243
+ items: {
1244
+ type: "string",
1245
+ minLength: 1
1246
+ },
1247
+ uniqueItems: !0
1248
+ },
1249
+ contextTypes: {
1250
+ type: "array",
1251
+ description: "Supported token storage contexts",
1252
+ items: {
1253
+ type: "string",
1254
+ enum: [
1255
+ "user",
1256
+ "organization"
1257
+ ]
1258
+ },
1259
+ minItems: 1,
1260
+ uniqueItems: !0
1261
+ },
1262
+ header: {
1263
+ type: "string",
1264
+ description: "Custom HTTP header name to put the token into (default: Authorization)",
1265
+ minLength: 1
1266
+ },
1267
+ prefix: {
1268
+ type: "string",
1269
+ description: "Custom token prefix in the Authorization header (default: Bearer; empty string for no prefix)"
1270
+ }
1271
+ },
1272
+ additionalProperties: !1
1273
+ },
1274
+ SlotConfig: {
1275
+ type: "object",
1276
+ description: "Configuration for a specific slot",
1277
+ required: [
1278
+ "entrypoint",
1279
+ "title",
1280
+ "contextLevel"
1281
+ ],
1282
+ properties: {
1283
+ entrypoint: {
1284
+ type: "string",
1285
+ description: "Entry point file path for the slot",
1286
+ minLength: 1
1287
+ },
1288
+ title: {
1289
+ type: "object",
1290
+ description: "Localized titles for the slot",
1291
+ required: [
1292
+ "ru",
1293
+ "en"
1294
+ ],
1295
+ properties: {
1296
+ ru: {
1297
+ type: "string",
1298
+ description: "Russian title",
1299
+ minLength: 1,
1300
+ maxLength: 32
1301
+ },
1302
+ en: {
1303
+ type: "string",
1304
+ description: "English title",
1305
+ minLength: 1,
1306
+ maxLength: 32
1307
+ }
1308
+ },
1309
+ additionalProperties: !1
1310
+ },
1311
+ contextLevel: {
1312
+ type: "string",
1313
+ description: "Level of context data provided to the slot",
1314
+ enum: [
1315
+ "basic",
1316
+ "full"
1317
+ ]
1318
+ },
1319
+ icon: {
1320
+ type: "object",
1321
+ description: "Optional slot icon (used by 'dock' slot for FAB)",
1322
+ required: [
1323
+ "url"
1324
+ ],
1325
+ properties: {
1326
+ url: {
1327
+ type: "string",
1328
+ description: "Relative path to the icon file (e.g. ./icon.svg)",
1329
+ minLength: 1
1330
+ }
1331
+ },
1332
+ additionalProperties: !1
1333
+ },
1334
+ description: {
1335
+ type: "object",
1336
+ description: "Localized descriptions for the slot",
1337
+ required: [
1338
+ "ru",
1339
+ "en"
1340
+ ],
1341
+ properties: {
1342
+ ru: {
1343
+ type: "string",
1344
+ description: "Russian description",
1345
+ minLength: 1,
1346
+ maxLength: 300
1347
+ },
1348
+ en: {
1349
+ type: "string",
1350
+ description: "English description",
1351
+ minLength: 1,
1352
+ maxLength: 300
1353
+ }
1354
+ },
1355
+ additionalProperties: !1
1356
+ }
1357
+ },
1358
+ additionalProperties: !1
1359
+ }
1360
+ }
1361
+ };
1362
+ }
1363
+ });
1364
+
1365
+ // src/core/manifest/manifestManager.ts
1366
+ var import_fs4, import_promises2, import_ajv, import_ajv_formats, validator, manifestPath, parseManifest, loadRaw, load2, validate, save2, update2, manifestManager, init_manifestManager = __esm({
1367
+ "src/core/manifest/manifestManager.ts"() {
1368
+ "use strict";
1369
+ import_fs4 = require("fs"), import_promises2 = require("fs/promises"), import_ajv = __toESM(require("ajv")), import_ajv_formats = __toESM(require("ajv-formats"));
1370
+ init_manifestPermissionsSchema2();
1371
+ init_formatValidationErrors();
1372
+ init_manifest_schema();
1373
+ validator = (() => {
1374
+ let schema = {
1375
+ ...manifest_schema_default,
1376
+ properties: {
1377
+ ...manifest_schema_default.properties,
1378
+ permissions: {
1379
+ ...manifest_schema_default.properties.permissions,
1380
+ properties: {
1381
+ ...manifest_schema_default.properties.permissions.properties,
1382
+ ...permissionsSchemaExtensions2
1383
+ }
1384
+ }
1385
+ }
1386
+ }, ajv = new import_ajv.default({ allErrors: !0, strict: !1 });
1387
+ return (0, import_ajv_formats.default)(ajv), ajv.compile(schema);
1388
+ })(), manifestPath = "./manifest.json", parseManifest = (content) => {
1389
+ let manifest;
1390
+ try {
1391
+ manifest = JSON.parse(content);
1392
+ } catch (error2) {
1393
+ throw error2 instanceof SyntaxError ? new Error(`File manifest.json contains invalid JSON: ${error2.message}`) : new Error(`Error reading manifest.json: ${error2.message}`);
1394
+ }
1395
+ return manifest;
1396
+ }, loadRaw = async () => {
1397
+ if (!(0, import_fs4.existsSync)(manifestPath))
1398
+ throw new Error(`File manifest.json not found at path: ${manifestPath}`);
1399
+ try {
1400
+ return await (0, import_promises2.readFile)(manifestPath, "utf8");
1401
+ } catch (error2) {
1402
+ throw error2 instanceof Error ? new Error(`Error reading manifest.json: ${error2.message}`) : new Error("Error loading manifest");
1403
+ }
1404
+ }, load2 = async () => {
1405
+ let manifestContent = await loadRaw();
1406
+ return parseManifest(manifestContent);
1407
+ }, validate = async () => {
1408
+ let manifest = await load2();
1409
+ if (!validator(manifest) && validator.errors) {
1410
+ let errorMessages2 = formatValidationErrors(validator.errors);
1411
+ throw new Error(
1412
+ `\u274C Manifest validation failed:
1413
+ ${errorMessages2}
1414
+
1415
+ \u{1F4A1} Ensure all required fields are filled according to the plugin documentation.`
1416
+ );
1417
+ }
1418
+ }, save2 = async (manifest) => {
1419
+ try {
1420
+ let content = JSON.stringify(manifest, null, 4);
1421
+ await (0, import_promises2.writeFile)(manifestPath, content, "utf8");
1422
+ } catch (error2) {
1423
+ throw error2 instanceof Error ? new Error(`Error saving manifest.json: ${error2.message}`) : new Error("Error saving manifest");
1424
+ }
1425
+ }, update2 = async (updates) => {
1426
+ let updatedManifest = { ...await load2(), ...updates };
1427
+ return await save2(updatedManifest), updatedManifest;
1428
+ }, manifestManager = {
1429
+ load: load2,
1430
+ loadRaw,
1431
+ validate,
1432
+ save: save2,
1433
+ update: update2
1434
+ };
1435
+ }
1436
+ });
1437
+
1438
+ // src/utils/marketplace.ts
1439
+ function validateMarketplaceAssets() {
1440
+ let marketplaceDir = import_path3.default.resolve(MARKETPLACE_DIR);
1441
+ ensurePathExists(
1442
+ marketplaceDir,
1443
+ "Marketplace folder not found. Create ./marketplace and add index.md and header-image.jpg before publishing."
1444
+ ), ensurePathExists(
1445
+ import_path3.default.join(marketplaceDir, MARKETPLACE_INDEX_FILE),
1446
+ "Marketplace description not found. Add ./marketplace/index.md before publishing."
1447
+ ), ensurePathExists(
1448
+ import_path3.default.join(marketplaceDir, MARKETPLACE_HEADER_IMAGE_FILE),
1449
+ "Marketplace header image not found. Add ./marketplace/header-image.jpg before publishing."
1450
+ ), ensurePathExists(
1451
+ import_path3.default.resolve(PUBLIC_DIR, PUBLIC_LOGO_FILE),
1452
+ "Plugin logo not found. Add ./public/logo.svg before publishing."
1453
+ );
1454
+ }
1455
+ function validateArchiveSources() {
1456
+ ensurePathExists(import_path3.default.resolve(DIST_DIR), "Dist folder not found. Build the project first."), ensurePathExists(
1457
+ import_path3.default.resolve(SRC_DIR),
1458
+ "Source folder not found. Add ./src before publishing."
1459
+ ), ensurePathExists(import_path3.default.resolve(MANIFEST_FILE), "manifest.json not found in plugin root."), validateMarketplaceAssets();
1460
+ }
1461
+ var import_fs5, import_path3, MARKETPLACE_DIR, MARKETPLACE_INDEX_FILE, MARKETPLACE_HEADER_IMAGE_FILE, PUBLIC_DIR, PUBLIC_LOGO_FILE, MANIFEST_FILE, DIST_DIR, SRC_DIR, ensurePathExists, validateManifestPublishingFields, ensureManifestCatalogFields, marketplacePaths, init_marketplace = __esm({
1462
+ "src/utils/marketplace.ts"() {
1463
+ "use strict";
1464
+ import_fs5 = __toESM(require("fs")), import_path3 = __toESM(require("path"));
1465
+ init_manifestManager();
1466
+ init_logger();
1467
+ MARKETPLACE_DIR = "marketplace", MARKETPLACE_INDEX_FILE = "index.md", MARKETPLACE_HEADER_IMAGE_FILE = "header-image.jpg", PUBLIC_DIR = "public", PUBLIC_LOGO_FILE = "logo.svg", MANIFEST_FILE = "manifest.json", DIST_DIR = "dist", SRC_DIR = "src", ensurePathExists = (targetPath, errorMessage) => {
1468
+ import_fs5.default.existsSync(targetPath) || (logger_default.error(errorMessage), process.exit(1));
1469
+ }, validateManifestPublishingFields = async () => {
1470
+ let manifest = await manifestManager.load();
1471
+ ensureManifestCatalogFields(manifest);
1472
+ }, ensureManifestCatalogFields = (manifest) => {
1473
+ (!manifest.name?.ru || !manifest.name?.en) && (logger_default.error(
1474
+ 'Manifest field "name" is required for publishing. Add localized "name.ru" and "name.en" to ./manifest.json.'
1475
+ ), process.exit(1)), (!manifest.description?.ru || !manifest.description?.en) && (logger_default.error(
1476
+ 'Manifest field "description" is required for publishing. Add localized "description.ru" and "description.en" to ./manifest.json.'
1477
+ ), process.exit(1));
1478
+ };
1479
+ marketplacePaths = {
1480
+ distDir: DIST_DIR,
1481
+ srcDir: SRC_DIR,
1482
+ marketplaceDir: MARKETPLACE_DIR,
1483
+ manifestFile: MANIFEST_FILE
1484
+ };
1485
+ }
1486
+ });
1487
+
1488
+ // src/utils/pluginPackageScripts.ts
1489
+ function readPluginPackageScripts(cwd = process.cwd()) {
1490
+ let packageJsonPath = import_path4.default.join(cwd, "package.json");
1491
+ return import_fs6.default.existsSync(packageJsonPath) ? JSON.parse(import_fs6.default.readFileSync(packageJsonPath, "utf-8")).scripts ?? {} : null;
1492
+ }
1493
+ function hasPluginScript(name, cwd = process.cwd()) {
1494
+ return !!readPluginPackageScripts(cwd)?.[name];
1495
+ }
1496
+ var import_fs6, import_path4, init_pluginPackageScripts = __esm({
1497
+ "src/utils/pluginPackageScripts.ts"() {
1498
+ "use strict";
1499
+ import_fs6 = __toESM(require("fs")), import_path4 = __toESM(require("path"));
1500
+ }
1501
+ });
1502
+
1503
+ // src/commands/submit/utils/runSubmitPrechecks.ts
1504
+ async function runSubmitPrechecks(options = {}) {
1505
+ if (options.skip) {
1506
+ logger_default.warning("Skipping pre-submit checks (--skip-checks).");
1507
+ return;
1508
+ }
1509
+ logger_default.separator(), logger_default.info("\u{1F50D} Pre-submit checks"), logger_default.separator(), await runStep("Validate manifest.json", () => manifestManager.validate()), await runStep("Check publishing metadata and assets", async () => {
1510
+ await validateManifestPublishingFields(), validateMarketplaceAssets();
1511
+ }), await runShellStep("Install dependencies", pluginCmd.install), await runShellStep("Run linter", pluginCmd.lint), hasPluginScript("typecheck") ? await runShellStep("Run typecheck", pluginCmd.typecheck) : logger_default.verbose('Skipping typecheck (no "typecheck" script in package.json).'), hasPluginScript("test") ? await runShellStep("Run tests", pluginCmd.test) : logger_default.warning(
1512
+ 'No "test" script in package.json \u2014 add tests before publishing, or run submit with --skip-checks.'
1513
+ ), await runShellStep("Check dependency vulnerabilities", pluginCmd.audit), logger_default.separator(), logger_default.success("Pre-submit checks passed"), logger_default.separator();
1514
+ }
1515
+ var import_picocolors4, stepStart, stepDone, runStep, runShellStep, init_runSubmitPrechecks = __esm({
1516
+ "src/commands/submit/utils/runSubmitPrechecks.ts"() {
1517
+ "use strict";
1518
+ import_picocolors4 = __toESM(require("picocolors"));
1519
+ init_manifestManager();
1520
+ init_execCommand();
1521
+ init_logger();
1522
+ init_marketplace();
1523
+ init_pluginPackageScripts();
1524
+ init_templateCommands();
1525
+ stepStart = (label) => {
1526
+ console.info(`${import_picocolors4.default.cyan("\u25B8")} ${label}`);
1527
+ }, stepDone = (label) => {
1528
+ console.info(`${import_picocolors4.default.green("\u2713")} ${label}`), console.info("");
1529
+ }, runStep = async (label, run) => {
1530
+ stepStart(label), await run(), stepDone(label);
1531
+ }, runShellStep = async (label, command) => {
1532
+ stepStart(label), console.info(import_picocolors4.default.dim(` $ ${command}`)), await execCommand(command), stepDone(label);
1533
+ };
1534
+ }
1535
+ });
1536
+
1537
+ // src/utils/buildArchive.ts
1538
+ async function buildArchive() {
1539
+ return validateArchiveSources(), (await manifestManager.load()).manifest_version === void 0 && (logger_default.error(
1540
+ `manifest_version is missing in manifest.json. Run "${CLI_NAME2} up" or add "manifest_version": 1 manually before uploading.`
1541
+ ), process.exit(1)), new Promise((resolve2, reject) => {
1542
+ let archive = (0, import_archiver.default)("zip", { zlib: { level: 9 } }), chunks = [];
1543
+ archive.on("data", (chunk) => chunks.push(chunk)), archive.on("end", () => {
1544
+ let buffer = Buffer.concat(chunks);
1545
+ if (logger_default.info(`\u{1F4E6} Archive created (${buffer.length} bytes)`), isVerboseEnabled()) {
1546
+ let debugPath = writeVerboseArtifact("archive/latest-upload.zip", buffer);
1547
+ logger_default.info(`[platform-api-debug] Saved archive copy to ${debugPath}`);
1548
+ }
1549
+ resolve2(buffer);
1550
+ }), archive.on("error", reject), archive.glob("**/*", {
1551
+ cwd: process.cwd(),
1552
+ ignore: ["node_modules/**", "dist/**", "**/.DS_Store"],
1553
+ dot: !0
1554
+ }), archive.file(import_path5.default.resolve(marketplacePaths.manifestFile), { name: "src/manifest.json" }), archive.glob(
1555
+ "**/*",
1556
+ {
1557
+ cwd: import_path5.default.resolve(marketplacePaths.distDir),
1558
+ ignore: ["**/.DS_Store"]
1559
+ },
1560
+ { prefix: "dist/" }
1561
+ ), archive.finalize();
1562
+ });
1563
+ }
1564
+ var import_path5, import_archiver, init_buildArchive = __esm({
1565
+ "src/utils/buildArchive.ts"() {
1566
+ "use strict";
1567
+ import_path5 = __toESM(require("path")), import_archiver = __toESM(require("archiver"));
1568
+ init_manifestManager();
1569
+ init_meta2();
1570
+ init_logger();
1571
+ init_marketplace();
1572
+ init_verbose();
1573
+ }
1574
+ });
1575
+
1576
+ // src/distributions/external/submit.ts
1577
+ async function submitExternal(options = {}) {
1578
+ await runSubmitPrechecks({ skip: options.skipChecks });
1579
+ let manifest = await manifestManager.load(), issueKey = (await pluginStateManager.load()).trackerIssueKey;
1580
+ if (issueKey)
1581
+ try {
1582
+ await getIssue(issueKey);
1583
+ } catch {
1584
+ issueKey = void 0;
1585
+ }
1586
+ let pluginId = manifest.id ?? (0, import_crypto.randomUUID)();
1587
+ manifest.id || await manifestManager.update({ id: pluginId });
1588
+ let manifestJson = await manifestManager.loadRaw();
1589
+ if (issueKey) {
1590
+ logger_default.verbose(`\u23F3 Updating issue ${issueKey} with latest manifest...`);
1591
+ let issueDescription = buildIssueDescription({
1592
+ pluginId,
1593
+ slug: manifest.slug,
1594
+ version: manifest.version,
1595
+ manifestJson
1596
+ });
1597
+ await updatePluginIssue(issueKey, { description: issueDescription });
1598
+ } else if (options.ticket === !1) {
1599
+ logger_default.warning(
1600
+ "Tracker issue is required for tracker-backed submit. Skipping ticket creation."
1601
+ );
1602
+ return;
1603
+ } else {
1604
+ logger_default.info("\u23F3 Creating plugin issue in Tracker...");
1605
+ let issue = await createPluginIssue({
1606
+ pluginId,
1607
+ slug: manifest.slug,
1608
+ version: manifest.version,
1609
+ manifestJson
1610
+ });
1611
+ await pluginStateManager.update({ trackerIssueKey: issue.key }), issueKey = issue.key, logger_default.info(` Tracker issue : ${issueKey}`);
1612
+ }
1613
+ logger_default.info("\u{1F528} Building plugin..."), await build(), logger_default.info("\u{1F4E6} Creating archive...");
1614
+ let archiveBuffer = await buildArchive(), archiveName = `${manifest.slug}-${manifest.version}.zip`;
1615
+ logger_default.verbose(`\u2B06\uFE0F Attaching ${archiveName} to ${issueKey}...`), await attachFileToIssue(issueKey, archiveBuffer, archiveName), await addIssueComment(
1616
+ issueKey,
1617
+ `Updated bundle: \`${archiveName}\` (${archiveBuffer.length} bytes)`
1618
+ ), logger_default.verbose(`\u23F3 Fetching available transitions for ${issueKey}...`);
1619
+ let transitions = await getIssueTransitions(issueKey), submitTransition = transitions.find(
1620
+ (t) => t.display?.toLowerCase().includes(SUBMIT_TRANSITION_DISPLAY) || t.id?.toLowerCase().includes("waitingforapprove") || t.id?.toLowerCase().includes("waiting")
1621
+ );
1622
+ if (!submitTransition) {
1623
+ let available = transitions.map((t) => `"${t.display ?? t.id}"`).join(", ");
1624
+ logger_default.error(
1625
+ `Could not find a "Waiting for approve" transition on ${issueKey}. Available: ${available}`
1626
+ );
1627
+ return;
1628
+ }
1629
+ logger_default.info("\u{1F680} Submitting plugin for review..."), await executeIssueTransition(issueKey, submitTransition.id), await addIssueComment(issueKey, `Submitted version \`${manifest.version}\` for review.`), logger_default.success("Plugin submitted for review!"), logger_default.info(` Tracker issue : ${issueKey}`), logger_default.info(` Version : ${manifest.version}`), logger_default.newLine();
1630
+ }
1631
+ var import_crypto, SUBMIT_TRANSITION_DISPLAY, init_submit = __esm({
1632
+ "src/distributions/external/submit.ts"() {
1633
+ "use strict";
1634
+ import_crypto = require("crypto");
1635
+ init_build();
1636
+ init_runSubmitPrechecks();
1637
+ init_manifestManager();
1638
+ init_pluginStateManager();
1639
+ init_buildArchive();
1640
+ init_logger();
1641
+ init_tracker();
1642
+ SUBMIT_TRANSITION_DISPLAY = "waiting for approve";
1643
+ }
1644
+ });
1645
+
200
1646
  // src/distributions/external/registerCommands.ts
201
1647
  var registerCommands_exports = {};
202
1648
  __export(registerCommands_exports, {
203
1649
  registerDistributionCommands: () => registerDistributionCommands
204
1650
  });
205
1651
  function registerDistributionCommands(program) {
206
- registerConfigCommand(program, CLI_NAME);
1652
+ 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(
1653
+ withErrorHandling(async () => {
1654
+ logoutExternal();
1655
+ })
1656
+ ), program.command("submit").description("build plugin, create a Tracker issue in PLUGINMOD, and submit for review").addOption(skipChecksOption).action(withErrorHandling(submitExternal)), program.command("list").description("list all your plugins and their moderation status").action(withErrorHandling(listExternal)), program.command("info [issue-key]").description(
1657
+ "show moderation status of a plugin (uses .tracker-plugin issue key if not provided)"
1658
+ ).action(withErrorHandling(infoExternal));
207
1659
  }
208
1660
  var init_registerCommands = __esm({
209
1661
  "src/distributions/external/registerCommands.ts"() {
210
1662
  "use strict";
1663
+ init_options();
211
1664
  init_registerCommand();
1665
+ init_withErrorHandling();
1666
+ init_info();
1667
+ init_list();
1668
+ init_login();
212
1669
  init_meta();
1670
+ init_submit();
213
1671
  }
214
1672
  });
215
1673
 
@@ -276,7 +1734,7 @@ function getPlatformBaseUrl() {
276
1734
  return cfg.api.platformBaseUrl;
277
1735
  }
278
1736
  function getTrackerBaseUrl() {
279
- return TRACKER_BASE_URL;
1737
+ return TRACKER_BASE_URL2;
280
1738
  }
281
1739
  function getOAuthTokenUrl() {
282
1740
  let cfg = requireConfig();
@@ -287,11 +1745,11 @@ function getOAuthTokenUrl() {
287
1745
  function getUpdateCheckInfo() {
288
1746
  return null;
289
1747
  }
290
- var TRACKER_BASE_URL, init_hosts = __esm({
1748
+ var TRACKER_BASE_URL2, init_hosts = __esm({
291
1749
  "src/distributions/external/hosts.ts"() {
292
1750
  "use strict";
293
1751
  init_manager();
294
- TRACKER_BASE_URL = "https://tracker.yandex.ru";
1752
+ TRACKER_BASE_URL2 = "https://api.tracker.yandex.net/v3";
295
1753
  }
296
1754
  });
297
1755
 
@@ -299,6 +1757,7 @@ var TRACKER_BASE_URL, init_hosts = __esm({
299
1757
  var templateSubstitution_exports = {};
300
1758
  __export(templateSubstitution_exports, {
301
1759
  applySubstitutions: () => applySubstitutions,
1760
+ overlayDirName: () => overlayDirName,
302
1761
  templateDeps: () => templateDeps
303
1762
  });
304
1763
  function rewritePackageJson(content) {
@@ -306,8 +1765,6 @@ function rewritePackageJson(content) {
306
1765
  if (pkg.dependencies) {
307
1766
  let next = {};
308
1767
  for (let [name, version] of Object.entries(pkg.dependencies)) {
309
- if (PACKAGE_DROP.has(name))
310
- continue;
311
1768
  let renamed = PACKAGE_RENAME[name] ?? name;
312
1769
  next[renamed] = ADDED_DEPS[renamed] ?? version;
313
1770
  }
@@ -328,62 +1785,52 @@ function rewriteImports(content) {
328
1785
  }
329
1786
  return result;
330
1787
  }
331
- function rewriteScss(content) {
332
- return content.split(`
333
- `).filter((line) => {
334
- let trimmed = line.trim();
335
- return trimmed.startsWith("@import") ? ![...PACKAGE_DROP].some((pkg) => trimmed.includes(pkg)) : !0;
336
- }).join(`
337
- `);
338
- }
339
1788
  function rewriteNpmrc(content) {
340
1789
  return content.split(`
341
1790
  `).filter((line) => !/^registry\s*=\s*https?:\/\/npm\.yandex-team\.ru/.test(line.trim())).join(`
342
1791
  `);
343
1792
  }
344
1793
  function applySubstitutions(filePath, content) {
345
- let name = import_path2.default.basename(filePath), ext = import_path2.default.extname(filePath);
1794
+ let name = import_path6.default.basename(filePath), ext = import_path6.default.extname(filePath);
346
1795
  if (name === "package.json")
347
1796
  return Buffer.from(rewritePackageJson(content.toString("utf8")), "utf8");
348
1797
  if (name === "npmrc.template" || name === ".npmrc")
349
1798
  return Buffer.from(rewriteNpmrc(content.toString("utf8")), "utf8");
350
- if (ext === ".scss" || ext === ".css")
351
- return Buffer.from(rewriteScss(content.toString("utf8")), "utf8");
352
1799
  if ([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"].includes(ext)) {
353
- let text = content.toString("utf8"), rewritten = rewriteImports(text);
354
- if (rewritten !== text)
1800
+ let original = content.toString("utf8"), rewritten = rewriteImports(original);
1801
+ if (rewritten !== original)
355
1802
  return Buffer.from(rewritten, "utf8");
356
1803
  }
357
1804
  return content;
358
1805
  }
359
- var import_path2, PACKAGE_RENAME, PACKAGE_DROP, ADDED_DEPS, templateDeps, init_templateSubstitution = __esm({
1806
+ var import_path6, PACKAGE_RENAME, ADDED_DEPS, templateDeps, overlayDirName, init_templateSubstitution = __esm({
360
1807
  "src/distributions/external/templateSubstitution.ts"() {
361
1808
  "use strict";
362
- import_path2 = __toESM(require("path")), PACKAGE_RENAME = {
1809
+ import_path6 = __toESM(require("path")), PACKAGE_RENAME = {
363
1810
  "@yandex-data-ui/tracker-plugin-sdk-react": "@weavix/sdk-react",
364
1811
  "@yandex-data-ui/tracker-pub-api-types": "@weavix/tracker-api-types"
365
- }, PACKAGE_DROP = /* @__PURE__ */ new Set(["@yandex-data-ui/gravity-themes"]), ADDED_DEPS = {
1812
+ }, ADDED_DEPS = {
366
1813
  "@weavix/sdk-core": "latest",
367
1814
  "@weavix/sdk-react": "latest",
368
1815
  "@weavix/tracker-api-types": "latest"
369
- }, templateDeps = ["@weavix/sdk-core", "@weavix/sdk-react", "@weavix/tracker-api-types"];
1816
+ }, templateDeps = ["@weavix/sdk-core", "@weavix/sdk-react", "@weavix/tracker-api-types"], overlayDirName = "_external";
370
1817
  }
371
1818
  });
372
1819
 
373
1820
  // src/index.ts
374
- var import_commander = require("commander");
375
-
376
- // src/distribution/meta.ts
377
- var impl = (init_meta(), __toCommonJS(meta_exports)), { CLI_NAME: CLI_NAME2, CLI_DESCRIPTION: CLI_DESCRIPTION2, CLI_HELP_TEXT: CLI_HELP_TEXT2 } = impl;
1821
+ var import_commander2 = require("commander");
1822
+ init_meta2();
378
1823
 
379
1824
  // src/distribution/registerCommands.ts
380
- var impl2 = (init_registerCommands(), __toCommonJS(registerCommands_exports)), { registerDistributionCommands: registerDistributionCommands2 } = impl2;
1825
+ init_flag();
1826
+ var impl3 = (init_registerCommands(), __toCommonJS(registerCommands_exports)), { registerDistributionCommands: registerDistributionCommands2 } = impl3;
381
1827
 
382
1828
  // src/utils/checkUpdate.ts
383
- var import_node_fetch = __toESM(require("node-fetch"));
1829
+ var import_node_fetch2 = __toESM(require("node-fetch"));
384
1830
 
385
1831
  // src/distribution/hosts.ts
386
- var impl3 = (init_hosts(), __toCommonJS(hosts_exports)), {
1832
+ init_flag();
1833
+ var impl4 = (init_hosts(), __toCommonJS(hosts_exports)), {
387
1834
  getS3Endpoint: getS3Endpoint2,
388
1835
  getMdsEndpoint: getMdsEndpoint2,
389
1836
  getS3Region: getS3Region2,
@@ -393,55 +1840,48 @@ var impl3 = (init_hosts(), __toCommonJS(hosts_exports)), {
393
1840
  getTrackerBaseUrl: getTrackerBaseUrl2,
394
1841
  getOAuthTokenUrl: getOAuthTokenUrl2,
395
1842
  getUpdateCheckInfo: getUpdateCheckInfo2
396
- } = impl3;
397
-
398
- // src/utils/checkUpdate.ts
399
- init_logger();
400
- var checkUpdate = async (version) => {
401
- let info2 = getUpdateCheckInfo2();
402
- if (info2)
403
- try {
404
- let response = await (0, import_node_fetch.default)(`${info2.registryUrl}/${info2.packageName}/latest`);
405
- if (!response.ok)
406
- return;
407
- let latest = await response.json();
408
- latest.version !== version && (logger_default.newLine(), logger_default.info(
409
- `\u{1F514} Update available ${version} \u2192 ${latest.version}
410
- Run: npm i -g ${info2.packageName}@latest --registry=${info2.registryUrl}`
411
- ));
412
- } catch {
413
- }
414
- };
415
-
416
- // src/utils/execCommand.ts
417
- var import_execa = require("execa"), execCommand = async (command, cwd = process.cwd()) => {
418
- await (0, import_execa.execa)(command, {
419
- cwd,
420
- shell: !0,
421
- stdio: "inherit"
422
- });
423
- };
424
-
425
- // src/commands/build.ts
426
- init_logger();
1843
+ } = impl4;
427
1844
 
428
- // src/commands/constants/templateCommands.ts
429
- var pluginCmd = {
430
- install: "npm install",
431
- build: "npm run build",
432
- dev: "npm run dev",
433
- lint: "npm run lint"
1845
+ // src/utils/checkUpdate.ts
1846
+ init_logger();
1847
+ var SEMVER_RE = /^(\d+)\.(\d+)\.(\d+)$/, DIAGNOSTIC_FLAGS = /* @__PURE__ */ new Set(["--version", "-V", "--help", "-h", "help"]), parse = (v) => {
1848
+ let m = SEMVER_RE.exec(v);
1849
+ return m ? { major: +m[1], minor: +m[2], patch: +m[3] } : null;
1850
+ }, isDiagnosticInvocation = () => {
1851
+ let args = process.argv.slice(2);
1852
+ return args.length === 0 ? !0 : args.some((a) => DIAGNOSTIC_FLAGS.has(a));
1853
+ }, classify = (current, latest) => latest.major > current.major ? "minorOrMajor" : latest.major < current.major ? "none" : latest.minor > current.minor ? "minorOrMajor" : latest.minor < current.minor ? "none" : latest.patch > current.patch ? "patch" : "none", checkUpdate = async (version) => {
1854
+ if (version === "unknown" || isDiagnosticInvocation() || process.env.TRACKER_CLI_SKIP_UPDATE_CHECK) return;
1855
+ let info2 = getUpdateCheckInfo2();
1856
+ if (!info2) return;
1857
+ let current = parse(version);
1858
+ if (current)
1859
+ try {
1860
+ let response = await (0, import_node_fetch2.default)(`${info2.registryUrl}/${info2.packageName}/latest`);
1861
+ if (!response.ok) return;
1862
+ let json = await response.json(), latest = parse(json.version);
1863
+ if (!latest) return;
1864
+ let kind = classify(current, latest);
1865
+ if (kind === "none") return;
1866
+ let installCmd = `npm i -g ${info2.packageName}@latest --registry=${info2.registryUrl}`;
1867
+ if (kind === "minorOrMajor") {
1868
+ logger_default.newLine(), logger_default.error(
1869
+ `Update required ${version} \u2192 ${json.version}
1870
+ This release is not backward-compatible with your installed version.`
1871
+ ), logger_default.suggest(installCmd), process.exit(1);
1872
+ return;
1873
+ }
1874
+ logger_default.newLine(), logger_default.info(`\u{1F514} Update available ${version} \u2192 ${json.version}
1875
+ Run: ${installCmd}`);
1876
+ } catch {
1877
+ }
434
1878
  };
435
1879
 
436
- // src/commands/build.ts
437
- var build = async ({ environment = "production" } = {}) => {
438
- logger_default.info("\u{1F528} Building project..."), await execCommand(pluginCmd.install), await execCommand(
439
- environment ? `VITE_DEPLOY_ENV=${environment} ${pluginCmd.build}` : pluginCmd.build
440
- );
441
- };
1880
+ // src/index.ts
1881
+ init_build();
442
1882
 
443
1883
  // src/commands/create/index.ts
444
- var path8 = __toESM(require("path")), import_prompts2 = require("@inquirer/prompts");
1884
+ var path13 = __toESM(require("path")), import_prompts3 = require("@inquirer/prompts");
445
1885
 
446
1886
  // src/core/manifest/constants.ts
447
1887
  var DATA_PERMISSIONS = [
@@ -526,9 +1966,16 @@ var TEMPLATES = [
526
1966
  "navigation",
527
1967
  "trigger.action",
528
1968
  "project.action",
1969
+ "project.block",
1970
+ "project.tab",
529
1971
  "portfolio.action",
1972
+ "portfolio.block",
1973
+ "portfolio.tab",
530
1974
  "goal.action",
531
- "attachment.viewer.action"
1975
+ "goal.block",
1976
+ "goal.tab",
1977
+ "attachment.viewer.action",
1978
+ "board.tab"
532
1979
  ];
533
1980
  var TEMPLATE_SLOTS = {
534
1981
  default: [],
@@ -539,25 +1986,33 @@ var TEMPLATE_SLOTS = {
539
1986
  navigation: ["navigation"],
540
1987
  "trigger.action": ["trigger.create.action", "trigger.edit.action"],
541
1988
  "project.action": ["project.action"],
1989
+ "project.block": ["project.block"],
1990
+ "project.tab": ["project.tab"],
542
1991
  "portfolio.action": ["portfolio.action"],
1992
+ "portfolio.block": ["portfolio.block"],
1993
+ "portfolio.tab": ["portfolio.tab"],
543
1994
  "goal.action": ["goal.action"],
544
- "attachment.viewer.action": ["attachment.viewer.action"]
1995
+ "goal.block": ["goal.block"],
1996
+ "goal.tab": ["goal.tab"],
1997
+ "attachment.viewer.action": ["attachment.viewer.action"],
1998
+ "board.tab": ["board.tab"]
545
1999
  };
546
2000
 
547
2001
  // src/commands/create/index.ts
2002
+ init_meta2();
548
2003
  init_logger();
549
2004
 
550
2005
  // src/commands/create/utils/getWelcomeMessage.ts
551
- var import_picocolors2 = __toESM(require("picocolors")), getWelcomeMessage = (pwd) => `
552
- ${import_picocolors2.default.bold(import_picocolors2.default.white("\u{1F680} Create new tracker plugin"))}
2006
+ var import_picocolors5 = __toESM(require("picocolors")), getWelcomeMessage = (pwd) => `
2007
+ ${import_picocolors5.default.bold(import_picocolors5.default.white("\u{1F680} Create new tracker plugin"))}
553
2008
 
554
- ${import_picocolors2.default.dim(`\u{1F4C1} Creating an app in your current directory: ${pwd}`)}
2009
+ ${import_picocolors5.default.dim(`\u{1F4C1} Creating an app in your current directory: ${pwd}`)}
555
2010
 
556
- ${import_picocolors2.default.dim("Press")} ${import_picocolors2.default.yellow("Ctrl+C")} ${import_picocolors2.default.dim("to cancel.")}
2011
+ ${import_picocolors5.default.dim("Press")} ${import_picocolors5.default.yellow("Ctrl+C")} ${import_picocolors5.default.dim("to cancel.")}
557
2012
  `;
558
2013
 
559
2014
  // src/commands/create/utils/initManifest.ts
560
- var fs = __toESM(require("fs")), path2 = __toESM(require("path"));
2015
+ var fs5 = __toESM(require("fs")), path7 = __toESM(require("path"));
561
2016
 
562
2017
  // src/commands/create/utils/generateManifest.ts
563
2018
  function buildSlots(template, slotTitle) {
@@ -565,7 +2020,8 @@ function buildSlots(template, slotTitle) {
565
2020
  if (slotNames.length === 0) return;
566
2021
  let slotEntry = {
567
2022
  entrypoint: "index.html",
568
- title: { ru: slotTitle, en: slotTitle }
2023
+ title: { ru: slotTitle, en: slotTitle },
2024
+ contextLevel: "basic"
569
2025
  };
570
2026
  return {
571
2027
  tracker: Object.fromEntries(slotNames.map((slotName) => [slotName, [slotEntry]]))
@@ -592,20 +2048,19 @@ var generateManifest = (answers) => ({
592
2048
 
593
2049
  // src/commands/create/utils/initManifest.ts
594
2050
  var initManifest = ({ answers, targetDir }) => {
595
- let generatedManifest = generateManifest(answers), manifestPath2 = path2.join(targetDir, "manifest.json");
596
- fs.writeFileSync(manifestPath2, JSON.stringify(generatedManifest, null, 2), "utf-8");
2051
+ let generatedManifest = generateManifest(answers), manifestPath2 = path7.join(targetDir, "manifest.json");
2052
+ fs5.writeFileSync(manifestPath2, JSON.stringify(generatedManifest, null, 2), "utf-8");
597
2053
  };
598
2054
 
599
2055
  // src/commands/create/utils/initTemplate.ts
600
- var fs4 = __toESM(require("fs")), path7 = __toESM(require("path"));
601
-
602
- // src/utils/copyDirectory.ts
603
- var fs2 = __toESM(require("fs")), import_path3 = __toESM(require("path")), import_tinyglobby = require("tinyglobby");
2056
+ var fs8 = __toESM(require("fs")), path12 = __toESM(require("path"));
604
2057
 
605
2058
  // src/distribution/templateSubstitution.ts
606
- var impl4 = (init_templateSubstitution(), __toCommonJS(templateSubstitution_exports)), { applySubstitutions: applySubstitutions2, templateDeps: templateDeps2 } = impl4;
2059
+ init_flag();
2060
+ var impl5 = (init_templateSubstitution(), __toCommonJS(templateSubstitution_exports)), { applySubstitutions: applySubstitutions2, overlayDirName: overlayDirName2, templateDeps: templateDeps2 } = impl5;
607
2061
 
608
2062
  // src/utils/copyDirectory.ts
2063
+ var fs6 = __toESM(require("fs")), import_path7 = __toESM(require("path")), import_tinyglobby = require("tinyglobby");
609
2064
  var resolveTargetFileName = (file) => file.endsWith(".template") ? "." + file.replace(".template", "") : file, copyDirectory = async (sourceDir, targetDir) => {
610
2065
  let files = await (0, import_tinyglobby.glob)(["**/*"], {
611
2066
  cwd: sourceDir,
@@ -614,38 +2069,35 @@ var resolveTargetFileName = (file) => file.endsWith(".template") ? "." + file.re
614
2069
  });
615
2070
  await Promise.all(
616
2071
  files.map(async (file) => {
617
- let sourcePath = import_path3.default.join(sourceDir, file), targetFile = resolveTargetFileName(file), targetPath = import_path3.default.join(targetDir, targetFile);
618
- await fs2.promises.mkdir(import_path3.default.dirname(targetPath), { recursive: !0 });
619
- let content = await fs2.promises.readFile(sourcePath), rewritten = applySubstitutions2(file, content);
620
- await fs2.promises.writeFile(targetPath, rewritten);
2072
+ let sourcePath = import_path7.default.join(sourceDir, file), targetFile = resolveTargetFileName(file), targetPath = import_path7.default.join(targetDir, targetFile);
2073
+ await fs6.promises.mkdir(import_path7.default.dirname(targetPath), { recursive: !0 });
2074
+ let content = await fs6.promises.readFile(sourcePath), rewritten = applySubstitutions2(file, content);
2075
+ await fs6.promises.writeFile(targetPath, rewritten);
621
2076
  })
622
2077
  );
623
2078
  };
624
2079
 
625
2080
  // src/utils/getProjectPath.ts
626
- var import_path4 = __toESM(require("path")), isDevelopment = () => __dirname.includes("/src/"), getProjectPath = (relativePath) => {
627
- let levelsUp = isDevelopment() ? "../.." : "..";
628
- return import_path4.default.resolve(__dirname, levelsUp, relativePath);
629
- }, getTemplatesBaseDir = () => getProjectPath("templates"), getTemplatePath = (filename) => import_path4.default.join(getTemplatesBaseDir(), "_shared", filename);
2081
+ var import_path8 = __toESM(require("path")), isDevelopment = () => __dirname.includes("/src/"), getProjectPath = (relativePath) => isDevelopment() ? import_path8.default.resolve(__dirname, "..", "..", relativePath) : import_path8.default.resolve(__dirname, relativePath), getTemplatesBaseDir = () => getProjectPath("templates"), getTemplatePath = (filename) => import_path8.default.join(getTemplatesBaseDir(), "_shared", filename);
630
2082
 
631
2083
  // src/commands/create/utils/initTemplate.ts
632
2084
  init_logger();
633
2085
 
634
2086
  // src/commands/create/utils/updatePackageJson.ts
635
- var fs3 = __toESM(require("fs")), path6 = __toESM(require("path")), updatePackageJson = (targetDir, packageSlug) => {
636
- let packageJsonPath = path6.join(targetDir, "package.json");
637
- if (fs3.existsSync(packageJsonPath)) {
638
- let packageJson = JSON.parse(fs3.readFileSync(packageJsonPath, "utf-8"));
639
- packageJson.name = packageSlug, fs3.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 4) + `
2087
+ var fs7 = __toESM(require("fs")), path11 = __toESM(require("path")), updatePackageJson = (targetDir, packageSlug) => {
2088
+ let packageJsonPath = path11.join(targetDir, "package.json");
2089
+ if (fs7.existsSync(packageJsonPath)) {
2090
+ let packageJson = JSON.parse(fs7.readFileSync(packageJsonPath, "utf-8"));
2091
+ packageJson.name = packageSlug, fs7.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 4) + `
640
2092
  `);
641
2093
  }
642
2094
  };
643
2095
 
644
2096
  // src/commands/create/utils/initTemplate.ts
645
2097
  var initTemplate = async ({ answers, targetDir }) => {
646
- fs4.existsSync(targetDir) || fs4.mkdirSync(targetDir, { recursive: !0 });
647
- let templatesBaseDir = getTemplatesBaseDir(), templatesDir = path7.join(templatesBaseDir, answers.template), sharedDir = path7.join(templatesBaseDir, "_shared");
648
- await copyDirectory(sharedDir, targetDir), await copyDirectory(templatesDir, targetDir), updatePackageJson(targetDir, answers.packageSlug), logger_default.info("Created template with marketplace publication requirements."), logger_default.info(
2098
+ fs8.existsSync(targetDir) || fs8.mkdirSync(targetDir, { recursive: !0 });
2099
+ let templatesBaseDir = getTemplatesBaseDir(), templatesDir = path12.join(templatesBaseDir, answers.template), sharedDir = path12.join(templatesBaseDir, "_shared"), overlayDir = path12.join(templatesBaseDir, overlayDirName2);
2100
+ 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(
649
2101
  "Before publishing, add ./marketplace/index.md, ./marketplace/header-image.jpg (784:325), and ./public/logo.svg (square)."
650
2102
  );
651
2103
  };
@@ -654,26 +2106,26 @@ var initTemplate = async ({ answers, targetDir }) => {
654
2106
  var DEFAULT_VERSION = "0.0.1";
655
2107
  async function create() {
656
2108
  logger_default.info(getWelcomeMessage(process.cwd()));
657
- let packageSlug = await (0, import_prompts2.input)({
2109
+ let packageSlug = await (0, import_prompts3.input)({
658
2110
  message: "Enter app slug (e.g., my-tracker-plugin):",
659
2111
  required: !0
660
- }), pluginName = await (0, import_prompts2.input)({
2112
+ }), pluginName = await (0, import_prompts3.input)({
661
2113
  message: "Enter plugin name:",
662
2114
  required: !0
663
- }), pluginDescription = await (0, import_prompts2.input)({
2115
+ }), pluginDescription = await (0, import_prompts3.input)({
664
2116
  message: "Enter plugin description:",
665
2117
  required: !0
666
- }), supportEmail = await (0, import_prompts2.input)({
2118
+ }), supportEmail = await (0, import_prompts3.input)({
667
2119
  message: "Enter support email:",
668
2120
  required: !0,
669
2121
  validate: (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value) || "Please enter a valid email address"
670
- }), template = await (0, import_prompts2.select)({
2122
+ }), template = await (0, import_prompts3.select)({
671
2123
  message: "Select a template:",
672
2124
  choices: TEMPLATES.map((templateName) => ({
673
2125
  name: templateName,
674
2126
  value: templateName
675
2127
  }))
676
- }), dataPermissions = await (0, import_prompts2.checkbox)({
2128
+ }), dataPermissions = await (0, import_prompts3.checkbox)({
677
2129
  message: "Select data permissions (some popular options):",
678
2130
  choices: TOP_DATA_PERMISSIONS.map((permission) => ({
679
2131
  name: permission,
@@ -690,567 +2142,28 @@ async function create() {
690
2142
  data: dataPermissions
691
2143
  },
692
2144
  version: DEFAULT_VERSION
693
- }, targetDir = path8.join(process.cwd(), answers.packageSlug);
2145
+ }, targetDir = path13.join(process.cwd(), answers.packageSlug);
694
2146
  await initTemplate({
695
2147
  answers,
696
2148
  targetDir
697
2149
  }), initManifest({
698
2150
  answers,
699
2151
  targetDir
700
- }), logger_default.newLine(), logger_default.success("Package generated!"), logger_default.commands("To get started, run", [
701
- `cd ${answers.packageSlug}`,
702
- "npm install",
703
- `${CLI_NAME2} debug`
704
- ]);
2152
+ }), logger_default.newLine(), logger_default.success("\u2705 Plugin created successfully!"), logger_default.newLine(), logger_default.info("\u{1F680} To start development:"), logger_default.commands("", [`cd ${answers.packageSlug}`, "npm install", `${CLI_NAME2} debug`]), logger_default.newLine(), logger_default.info(
2153
+ "\u{1F4CC} Important: After running debug, the plugin will be available in the Tracker interface,"
2154
+ ), logger_default.info("not at localhost. Open Tracker and check the plugin in the appropriate context.");
705
2155
  }
706
2156
 
707
2157
  // src/commands/debug/index.ts
708
- var import_fs6 = __toESM(require("fs")), import_path8 = __toESM(require("path"));
709
-
710
- // src/core/manifest/manifestManager.ts
711
- var import_fs2 = require("fs"), import_promises = require("fs/promises"), import_ajv = __toESM(require("ajv")), import_ajv_formats = __toESM(require("ajv-formats"));
712
-
713
- // src/core/manifest/formatValidationErrors.ts
714
- var priorityOrder = [
715
- "required",
716
- "type",
717
- "minLength",
718
- "format",
719
- "pattern",
720
- "enum",
721
- "additionalProperties",
722
- "uniqueItems"
723
- ], errorMessages = {
724
- required: (params) => `missing required property '${params.missingProperty}'`,
725
- type: (params) => `must be ${params.type}`,
726
- enum: (params) => `must be one of [${params.allowedValues.join(", ")}]`,
727
- pattern: (params) => `must match pattern ${params.pattern}`,
728
- format: (params) => `must be a valid ${params.format}`,
729
- minLength: () => "must not be empty",
730
- additionalProperties: (params) => `unexpected property '${params.additionalProperty}'`,
731
- uniqueItems: () => "must contain unique items"
732
- }, getPriority = (keyword) => {
733
- let index = priorityOrder.indexOf(keyword);
734
- return index === -1 ? priorityOrder.length : index;
735
- }, formatValidationErrors = (errors) => {
736
- let errorsByPath = {};
737
- for (let error2 of errors) {
738
- let path13 = error2.instancePath || "root";
739
- errorsByPath[path13] || (errorsByPath[path13] = []), errorsByPath[path13].push(error2);
740
- }
741
- return Object.entries(errorsByPath).map(([path13, pathErrors]) => {
742
- let error2 = [...pathErrors].sort(
743
- (a, b) => getPriority(a.keyword) - getPriority(b.keyword)
744
- )[0], formatter = errorMessages[error2.keyword], message = formatter ? formatter(error2.params) : error2.message;
745
- return ` - ${path13}: ${message}`;
746
- }).join(`
747
- `);
748
- };
749
-
750
- // src/core/manifest/manifest.schema.json
751
- var manifest_schema_default = {
752
- $schema: "http://json-schema.org/draft-07/schema#",
753
- title: "Manifest",
754
- description: "Schema for validating plugin manifest",
755
- type: "object",
756
- required: [
757
- "slug",
758
- "version",
759
- "permissions",
760
- "name",
761
- "description",
762
- "support"
763
- ],
764
- properties: {
765
- $schema: {
766
- type: "string"
767
- },
768
- id: {
769
- type: "string",
770
- description: "Unique identifier for the plugin ()",
771
- minLength: 3,
772
- maxLength: 63,
773
- pattern: "^[a-z0-9-]+$"
774
- },
775
- manifest_version: {
776
- type: "number",
777
- description: "Manifest format version",
778
- minimum: 1
779
- },
780
- supported_services: {
781
- type: "array",
782
- description: "Supported services for this plugin",
783
- items: {
784
- type: "string",
785
- enum: [
786
- "tracker"
787
- ]
788
- },
789
- minItems: 1,
790
- uniqueItems: !0
791
- },
792
- slug: {
793
- type: "string",
794
- description: "Unique identifier for the plugin (lowercase letters, numbers, hyphen)",
795
- minLength: 3,
796
- maxLength: 63,
797
- pattern: "^[a-z0-9-]+$"
798
- },
799
- version: {
800
- type: "string",
801
- description: "Version of the plugin (semver format required)",
802
- minLength: 1,
803
- pattern: "^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9.-]+)?(\\+[a-zA-Z0-9.-]+)?$"
804
- },
805
- name: {
806
- type: "object",
807
- description: "Localized plugin name",
808
- required: [
809
- "ru",
810
- "en"
811
- ],
812
- properties: {
813
- ru: {
814
- type: "string",
815
- description: "Russian name",
816
- minLength: 1,
817
- maxLength: 30
818
- },
819
- en: {
820
- type: "string",
821
- description: "English name",
822
- minLength: 1,
823
- maxLength: 30
824
- }
825
- },
826
- additionalProperties: !1
827
- },
828
- description: {
829
- type: "object",
830
- description: "Localized plugin description",
831
- required: [
832
- "ru",
833
- "en"
834
- ],
835
- properties: {
836
- ru: {
837
- type: "string",
838
- description: "Russian description",
839
- minLength: 1,
840
- maxLength: 255
841
- },
842
- en: {
843
- type: "string",
844
- description: "English description",
845
- minLength: 1,
846
- maxLength: 255
847
- }
848
- },
849
- additionalProperties: !1
850
- },
851
- support: {
852
- type: "array",
853
- description: "Support contact information",
854
- items: {
855
- type: "object",
856
- required: [
857
- "type",
858
- "value"
859
- ],
860
- properties: {
861
- type: {
862
- type: "string",
863
- description: "Type of support contact",
864
- enum: [
865
- "email"
866
- ]
867
- },
868
- value: {
869
- type: "string",
870
- description: "Contact value",
871
- minLength: 1,
872
- maxLength: 100
873
- }
874
- },
875
- additionalProperties: !1
876
- },
877
- minItems: 1
878
- },
879
- homepage: {
880
- type: "string",
881
- description: "Homepage URL for the plugin (http or https)",
882
- pattern: "^https?://",
883
- maxLength: 1e3
884
- },
885
- license: {
886
- type: "string",
887
- description: "License identifier (e.g., MIT, Apache-2.0)",
888
- minLength: 1,
889
- maxLength: 32
890
- },
891
- keywords: {
892
- type: "array",
893
- description: "Keywords for plugin discovery",
894
- items: {
895
- type: "string",
896
- minLength: 1,
897
- maxLength: 30
898
- },
899
- uniqueItems: !0
900
- },
901
- whatsnew: {
902
- type: "string",
903
- description: "What's new in this version",
904
- minLength: 1,
905
- maxLength: 300
906
- },
907
- externalHost: {
908
- type: "string",
909
- description: "External host URL for the plugin (https only)",
910
- format: "uri",
911
- pattern: "^https://",
912
- maxLength: 1e3
913
- },
914
- permissions: {
915
- type: "object",
916
- description: "Permissions required by the plugin",
917
- required: [
918
- "data"
919
- ],
920
- properties: {
921
- data: {
922
- type: "array",
923
- description: "Data access permissions",
924
- items: {
925
- type: "string",
926
- enum: [
927
- "tracker:issues:read",
928
- "tracker:issues:write",
929
- "tracker:issuetypes:read",
930
- "tracker:statuses:read",
931
- "tracker:queues:read",
932
- "tracker:fields:read",
933
- "tracker:entities:read",
934
- "tracker:attachments:read",
935
- "tracker:attachments:write",
936
- "tracker:applications:read",
937
- "tracker:boards:read",
938
- "tracker:boards:write",
939
- "tracker:bulk:read",
940
- "tracker:bulk:write",
941
- "tracker:bulkchange:read",
942
- "tracker:bulkchange:write",
943
- "tracker:charts:read",
944
- "tracker:commentTemplates:read",
945
- "tracker:commentTemplates:write",
946
- "tracker:components:read",
947
- "tracker:components:write",
948
- "tracker:data:read",
949
- "tracker:departments:read",
950
- "tracker:entities:write",
951
- "tracker:externalEventTypes:write",
952
- "tracker:externalEvents:write",
953
- "tracker:fields:write",
954
- "tracker:filterFolders:write",
955
- "tracker:filters:read",
956
- "tracker:filters:write",
957
- "tracker:goals:read",
958
- "tracker:goals:write",
959
- "tracker:groups:read",
960
- "tracker:issueTemplates:read",
961
- "tracker:issueTemplates:write",
962
- "tracker:links:read",
963
- "tracker:linktypes:read",
964
- "tracker:liveBoards:write",
965
- "tracker:localFields:read",
966
- "tracker:maillists:read",
967
- "tracker:maillists:write",
968
- "tracker:myself:read",
969
- "tracker:myself:write",
970
- "tracker:priorities:read",
971
- "tracker:queues:write",
972
- "tracker:reminders:read",
973
- "tracker:reminders:write",
974
- "tracker:remotelinks:read",
975
- "tracker:reports:read",
976
- "tracker:reports:write",
977
- "tracker:resolutions:read",
978
- "tracker:resources:read",
979
- "tracker:resources:write",
980
- "tracker:roles:read",
981
- "tracker:screens:read",
982
- "tracker:services:read",
983
- "tracker:sprints:read",
984
- "tracker:sprints:write",
985
- "tracker:system:write",
986
- "tracker:tags:read",
987
- "tracker:translations:read",
988
- "tracker:users:read",
989
- "tracker:users:write",
990
- "tracker:versions:read",
991
- "tracker:versions:write",
992
- "tracker:workflows:read",
993
- "tracker:workflows:write",
994
- "tracker:worklog:read",
995
- "tracker:worklog:write"
996
- ]
997
- },
998
- uniqueItems: !0
999
- },
1000
- ui: {
1001
- type: "array",
1002
- description: "UI permissions",
1003
- items: {
1004
- type: "string"
1005
- },
1006
- uniqueItems: !0
1007
- },
1008
- device: {
1009
- type: "array",
1010
- description: "Device permissions",
1011
- items: {
1012
- type: "string",
1013
- enum: [
1014
- "clipboard-write"
1015
- ]
1016
- },
1017
- uniqueItems: !0
1018
- },
1019
- external: {
1020
- type: "array",
1021
- description: "External permissions",
1022
- items: {
1023
- type: "string"
1024
- },
1025
- uniqueItems: !0
1026
- }
1027
- },
1028
- additionalProperties: !1
1029
- },
1030
- slots: {
1031
- type: "object",
1032
- description: "Configuration for service slots",
1033
- minProperties: 1,
1034
- properties: {
1035
- tracker: {
1036
- type: "object",
1037
- description: "Tracker service slots",
1038
- minProperties: 1,
1039
- properties: {
1040
- "issue.action": {
1041
- type: "array",
1042
- description: "Issue Action slot configurations",
1043
- minItems: 1,
1044
- items: {
1045
- $ref: "#/definitions/SlotConfig"
1046
- }
1047
- },
1048
- "issue.block": {
1049
- type: "array",
1050
- description: "Issue Block slot configurations",
1051
- minItems: 1,
1052
- items: {
1053
- $ref: "#/definitions/SlotConfig"
1054
- }
1055
- },
1056
- "issue.tab": {
1057
- type: "array",
1058
- description: "Issue Tab slot configurations",
1059
- minItems: 1,
1060
- items: {
1061
- $ref: "#/definitions/SlotConfig"
1062
- }
1063
- },
1064
- "issue.comment.action": {
1065
- type: "array",
1066
- description: "Issue Comment Action slot configurations",
1067
- minItems: 1,
1068
- items: {
1069
- $ref: "#/definitions/SlotConfig"
1070
- }
1071
- },
1072
- navigation: {
1073
- type: "array",
1074
- description: "Navigation slot configurations",
1075
- minItems: 1,
1076
- items: {
1077
- $ref: "#/definitions/SlotConfig"
1078
- }
1079
- },
1080
- "trigger.create.action": {
1081
- type: "array",
1082
- description: "Trigger Create Action slot configurations",
1083
- minItems: 1,
1084
- items: {
1085
- $ref: "#/definitions/SlotConfig"
1086
- }
1087
- },
1088
- "trigger.edit.action": {
1089
- type: "array",
1090
- description: "Trigger Edit Action slot configurations",
1091
- minItems: 1,
1092
- items: {
1093
- $ref: "#/definitions/SlotConfig"
1094
- }
1095
- },
1096
- "project.action": {
1097
- type: "array",
1098
- description: "Project Action slot configurations",
1099
- minItems: 1,
1100
- items: {
1101
- $ref: "#/definitions/SlotConfig"
1102
- }
1103
- },
1104
- "portfolio.action": {
1105
- type: "array",
1106
- description: "Portfolio Action slot configurations",
1107
- minItems: 1,
1108
- items: {
1109
- $ref: "#/definitions/SlotConfig"
1110
- }
1111
- },
1112
- "goal.action": {
1113
- type: "array",
1114
- description: "Goal Action slot configurations",
1115
- minItems: 1,
1116
- items: {
1117
- $ref: "#/definitions/SlotConfig"
1118
- }
1119
- },
1120
- "attachment.viewer.action": {
1121
- type: "array",
1122
- description: "Attachment Viewer Action slot configurations",
1123
- minItems: 1,
1124
- items: {
1125
- $ref: "#/definitions/SlotConfig"
1126
- }
1127
- }
1128
- },
1129
- additionalProperties: !1
1130
- }
1131
- },
1132
- additionalProperties: !1
1133
- }
1134
- },
1135
- additionalProperties: !1,
1136
- definitions: {
1137
- SlotConfig: {
1138
- type: "object",
1139
- description: "Configuration for a specific slot",
1140
- required: [
1141
- "entrypoint",
1142
- "title"
1143
- ],
1144
- properties: {
1145
- entrypoint: {
1146
- type: "string",
1147
- description: "Entry point file path for the slot",
1148
- minLength: 1
1149
- },
1150
- title: {
1151
- type: "object",
1152
- description: "Localized titles for the slot",
1153
- required: [
1154
- "ru",
1155
- "en"
1156
- ],
1157
- properties: {
1158
- ru: {
1159
- type: "string",
1160
- description: "Russian title",
1161
- minLength: 1,
1162
- maxLength: 32
1163
- },
1164
- en: {
1165
- type: "string",
1166
- description: "English title",
1167
- minLength: 1,
1168
- maxLength: 32
1169
- }
1170
- },
1171
- additionalProperties: !1
1172
- },
1173
- description: {
1174
- type: "object",
1175
- description: "Localized descriptions for the slot",
1176
- required: [
1177
- "ru",
1178
- "en"
1179
- ],
1180
- properties: {
1181
- ru: {
1182
- type: "string",
1183
- description: "Russian description",
1184
- minLength: 1,
1185
- maxLength: 300
1186
- },
1187
- en: {
1188
- type: "string",
1189
- description: "English description",
1190
- minLength: 1,
1191
- maxLength: 300
1192
- }
1193
- },
1194
- additionalProperties: !1
1195
- }
1196
- },
1197
- additionalProperties: !1
1198
- }
1199
- }
1200
- };
1201
-
1202
- // src/core/manifest/manifestManager.ts
1203
- var validator = (() => {
1204
- let ajv = new import_ajv.default({ allErrors: !0, strict: !1 });
1205
- return (0, import_ajv_formats.default)(ajv), ajv.compile(manifest_schema_default);
1206
- })(), manifestPath = "./manifest.json", parseManifest = (content) => {
1207
- let manifest;
1208
- try {
1209
- manifest = JSON.parse(content);
1210
- } catch (error2) {
1211
- throw error2 instanceof SyntaxError ? new Error(`File manifest.json contains invalid JSON: ${error2.message}`) : new Error(`Error reading manifest.json: ${error2.message}`);
1212
- }
1213
- return manifest;
1214
- }, loadRaw = async () => {
1215
- if (!(0, import_fs2.existsSync)(manifestPath))
1216
- throw new Error(`File manifest.json not found at path: ${manifestPath}`);
1217
- try {
1218
- return await (0, import_promises.readFile)(manifestPath, "utf8");
1219
- } catch (error2) {
1220
- throw error2 instanceof Error ? new Error(`Error reading manifest.json: ${error2.message}`) : new Error("Error loading manifest");
1221
- }
1222
- }, load = async () => {
1223
- let manifestContent = await loadRaw();
1224
- return parseManifest(manifestContent);
1225
- }, validate = async () => {
1226
- let manifest = await load();
1227
- if (!validator(manifest) && validator.errors) {
1228
- let errorMessages2 = formatValidationErrors(validator.errors);
1229
- throw new Error(`Manifest validation failed:
1230
- ${errorMessages2}`);
1231
- }
1232
- }, save = async (manifest) => {
1233
- try {
1234
- let content = JSON.stringify(manifest, null, 4);
1235
- await (0, import_promises.writeFile)(manifestPath, content, "utf8");
1236
- } catch (error2) {
1237
- throw error2 instanceof Error ? new Error(`Error saving manifest.json: ${error2.message}`) : new Error("Error saving manifest");
1238
- }
1239
- }, update = async (updates) => {
1240
- let updatedManifest = { ...await load(), ...updates };
1241
- return await save(updatedManifest), updatedManifest;
1242
- }, manifestManager = {
1243
- load,
1244
- loadRaw,
1245
- validate,
1246
- save,
1247
- update
1248
- };
2158
+ var import_fs10 = __toESM(require("fs")), import_path12 = __toESM(require("path"));
2159
+ init_manifestManager();
1249
2160
 
1250
2161
  // src/core/s3config/constants.ts
1251
2162
  var CONFIG_FILE_NAME = "config.json";
1252
2163
 
1253
2164
  // src/commands/debug/index.ts
2165
+ init_meta2();
2166
+ init_execCommand();
1254
2167
  init_logger();
1255
2168
 
1256
2169
  // src/utils/registerCleanup.ts
@@ -1262,8 +2175,12 @@ var registerCleanup = (cleanup) => {
1262
2175
  });
1263
2176
  };
1264
2177
 
2178
+ // src/commands/debug/index.ts
2179
+ init_templateCommands();
2180
+
1265
2181
  // src/commands/debug/utils/createDebugConfig.ts
1266
- var import_fs3 = __toESM(require("fs")), import_path5 = __toESM(require("path"));
2182
+ var import_fs7 = __toESM(require("fs")), import_path9 = __toESM(require("path"));
2183
+ init_manifestManager();
1267
2184
 
1268
2185
  // src/utils/convertManifestToConfig.ts
1269
2186
  function buildPluginDownloadUrl(env, id, version) {
@@ -1292,6 +2209,7 @@ var convertManifestToConfig = (manifest, environment) => {
1292
2209
  description: slotConfig.description,
1293
2210
  entrypoint: slotConfig.entrypoint,
1294
2211
  title: slotConfig.title,
2212
+ contextLevel: slotConfig.contextLevel,
1295
2213
  downloadUrl: buildPluginDownloadUrl(
1296
2214
  environment,
1297
2215
  manifest.slug,
@@ -1308,21 +2226,21 @@ var convertManifestToConfig = (manifest, environment) => {
1308
2226
 
1309
2227
  // src/commands/debug/utils/createDebugConfig.ts
1310
2228
  var createDebugConfig = async () => {
1311
- let manifest = await manifestManager.load(), config = convertManifestToConfig(manifest, "debug"), configPath = import_path5.default.join(process.cwd(), CONFIG_FILE_NAME);
1312
- import_fs3.default.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
2229
+ let manifest = await manifestManager.load(), config = convertManifestToConfig(manifest, "debug"), configPath = import_path9.default.join(process.cwd(), CONFIG_FILE_NAME);
2230
+ import_fs7.default.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
1313
2231
  };
1314
2232
 
1315
2233
  // src/commands/debug/utils/lockFile.ts
1316
- var import_fs4 = __toESM(require("fs")), import_path6 = __toESM(require("path")), LOCK_FILE_NAME = ".tracker-cli-debug.lock", getLockFilePath = () => import_path6.default.join(process.cwd(), LOCK_FILE_NAME), getRunningDebugPid = () => {
2234
+ var import_fs8 = __toESM(require("fs")), import_path10 = __toESM(require("path")), LOCK_FILE_NAME = ".tracker-cli-debug.lock", getLockFilePath = () => import_path10.default.join(process.cwd(), LOCK_FILE_NAME), getRunningDebugPid = () => {
1317
2235
  let lockPath = getLockFilePath();
1318
- if (!import_fs4.default.existsSync(lockPath))
2236
+ if (!import_fs8.default.existsSync(lockPath))
1319
2237
  return null;
1320
2238
  try {
1321
- let pid = JSON.parse(import_fs4.default.readFileSync(lockPath, "utf-8")).pid;
2239
+ let pid = JSON.parse(import_fs8.default.readFileSync(lockPath, "utf-8")).pid;
1322
2240
  return process.kill(pid, 0), pid;
1323
2241
  } catch {
1324
2242
  try {
1325
- import_fs4.default.unlinkSync(lockPath);
2243
+ import_fs8.default.unlinkSync(lockPath);
1326
2244
  } catch {
1327
2245
  }
1328
2246
  return null;
@@ -1330,18 +2248,19 @@ var import_fs4 = __toESM(require("fs")), import_path6 = __toESM(require("path"))
1330
2248
  }, createLockFile = () => {
1331
2249
  let lockPath = getLockFilePath(), lockData = {
1332
2250
  pid: process.pid
1333
- }, fd = import_fs4.default.openSync(lockPath, "wx");
1334
- import_fs4.default.writeSync(fd, JSON.stringify(lockData, null, 2)), import_fs4.default.closeSync(fd);
2251
+ }, fd = import_fs8.default.openSync(lockPath, "wx");
2252
+ import_fs8.default.writeSync(fd, JSON.stringify(lockData, null, 2)), import_fs8.default.closeSync(fd);
1335
2253
  }, removeLockFile = () => {
1336
2254
  let lockPath = getLockFilePath();
1337
- import_fs4.default.existsSync(lockPath) && import_fs4.default.unlinkSync(lockPath);
2255
+ import_fs8.default.existsSync(lockPath) && import_fs8.default.unlinkSync(lockPath);
1338
2256
  };
1339
2257
 
1340
2258
  // src/commands/debug/utils/watchManifest.ts
1341
- var import_fs5 = __toESM(require("fs")), import_path7 = __toESM(require("path"));
2259
+ var import_fs9 = __toESM(require("fs")), import_path11 = __toESM(require("path"));
2260
+ init_manifestManager();
1342
2261
  init_logger();
1343
2262
  var watchManifest = () => {
1344
- let manifestPath2 = import_path7.default.join(process.cwd(), "manifest.json"), debounceTimer = null, watcher = import_fs5.default.watch(manifestPath2, async (eventType) => {
2263
+ let manifestPath2 = import_path11.default.join(process.cwd(), "manifest.json"), debounceTimer = null, watcher = import_fs9.default.watch(manifestPath2, async (eventType) => {
1345
2264
  eventType === "change" && (debounceTimer && clearTimeout(debounceTimer), debounceTimer = setTimeout(async () => {
1346
2265
  try {
1347
2266
  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");
@@ -1365,53 +2284,71 @@ Please stop the existing instance before starting a new one.
1365
2284
  If you lost the terminal tab, you can kill the process with:
1366
2285
  kill ${runningPid}`
1367
2286
  ), process.exit(1));
1368
- let configPath = import_path8.default.join(process.cwd(), CONFIG_FILE_NAME);
2287
+ let configPath = import_path12.default.join(process.cwd(), CONFIG_FILE_NAME);
1369
2288
  options.lint && await manifestManager.validate(), await createDebugConfig();
1370
2289
  let watcher = watchManifest(), cleanup = () => {
1371
- watcher.close(), import_fs6.default.existsSync(configPath) && import_fs6.default.unlinkSync(configPath), removeLockFile();
2290
+ watcher.close(), import_fs10.default.existsSync(configPath) && import_fs10.default.unlinkSync(configPath), removeLockFile();
1372
2291
  };
1373
- registerCleanup(cleanup), createLockFile(), await execCommand(pluginCmd.dev), cleanup();
2292
+ registerCleanup(cleanup), createLockFile(), logger_default.newLine(), logger_default.info("\u{1F527} Debug mode started!"), logger_default.newLine(), logger_default.info("\u{1F4CC} The plugin is now available in the Tracker interface."), logger_default.info("Open Tracker and check the plugin functionality in the appropriate context."), logger_default.newLine(), logger_default.info("\u26A0\uFE0F Do not try to open localhost in the browser - the plugin works"), logger_default.info("only inside Tracker through a special loading mechanism."), logger_default.newLine(), logger_default.info("\u{1F504} Code changes will be automatically reloaded."), logger_default.info("Press Ctrl+C to stop."), logger_default.newLine(), await execCommand(pluginCmd.dev), cleanup();
1374
2293
  }
1375
2294
 
1376
2295
  // src/commands/lint.ts
2296
+ init_manifestManager();
2297
+ init_execCommand();
1377
2298
  init_logger();
2299
+ init_templateCommands();
1378
2300
  async function lint() {
1379
2301
  logger_default.info("\u{1F50D} Running manifest.json validation..."), await manifestManager.validate(), logger_default.info("\u{1F50D} Running code lint check..."), await execCommand(pluginCmd.lint);
1380
2302
  }
1381
2303
 
1382
2304
  // src/commands/up/utils/copyTemplateFiles.ts
1383
- var import_fs7 = require("fs"), import_promises2 = require("fs/promises");
2305
+ var import_fs11 = require("fs"), import_promises3 = require("fs/promises");
1384
2306
  var copyTemplateFiles = async (filenames) => {
1385
2307
  await Promise.all(
1386
2308
  filenames.map(async (filename) => {
1387
2309
  let templatePath = getTemplatePath(filename), targetPath = `./${filename}`;
1388
- if ((0, import_fs7.existsSync)(templatePath) && (0, import_fs7.existsSync)(targetPath)) {
1389
- let content = await (0, import_promises2.readFile)(templatePath), rewritten = applySubstitutions2(filename, content);
1390
- await (0, import_promises2.writeFile)(targetPath, rewritten);
2310
+ if ((0, import_fs11.existsSync)(templatePath) && (0, import_fs11.existsSync)(targetPath)) {
2311
+ let content = await (0, import_promises3.readFile)(templatePath), rewritten = applySubstitutions2(filename, content);
2312
+ await (0, import_promises3.writeFile)(targetPath, rewritten);
1391
2313
  }
1392
2314
  })
1393
2315
  );
1394
2316
  };
1395
2317
 
1396
2318
  // src/commands/up/utils/updateManifestCompatibility.ts
2319
+ init_manifestManager();
2320
+ function addDefaultContextLevel(slots) {
2321
+ if (!slots)
2322
+ return;
2323
+ let updatedSlots = {}, updates = [];
2324
+ for (let [service, serviceSlots] of Object.entries(slots))
2325
+ if (serviceSlots) {
2326
+ updatedSlots[service] = {};
2327
+ for (let [slot, slotConfigs] of Object.entries(serviceSlots))
2328
+ slotConfigs && (updatedSlots[service][slot] = slotConfigs.map((slotConfig) => "contextLevel" in slotConfig ? slotConfig : (updates.push(slotConfig), Object.assign({}, slotConfig, { contextLevel: "basic" }))));
2329
+ }
2330
+ return updates.length > 0 ? updatedSlots : void 0;
2331
+ }
1397
2332
  async function updateManifestCompatibility() {
1398
2333
  let manifest = await manifestManager.load(), updates = {};
1399
- "manifest_version" in manifest || (updates.manifest_version = 1), "supported_services" in manifest || (updates.supported_services = ["tracker"]), Object.keys(updates).length > 0 && await manifestManager.update(updates);
2334
+ "manifest_version" in manifest || (updates.manifest_version = 1), "supported_services" in manifest || (updates.supported_services = ["tracker"]);
2335
+ let updatedSlots = addDefaultContextLevel(manifest.slots);
2336
+ updatedSlots && (updates.slots = updatedSlots), Object.keys(updates).length > 0 && await manifestManager.update(updates);
1400
2337
  }
1401
2338
 
1402
2339
  // src/commands/up/utils/updatePackageDependencies.ts
1403
- var import_fs8 = require("fs"), import_promises3 = require("fs/promises");
2340
+ var import_fs12 = require("fs"), import_promises4 = require("fs/promises");
1404
2341
  var updatePackageDependencies = async (dependencies) => {
1405
2342
  let packageJsonPath = "./package.json", templatePackageJsonPath = getTemplatePath("package.json");
1406
- if (!(0, import_fs8.existsSync)(packageJsonPath) || !(0, import_fs8.existsSync)(templatePackageJsonPath))
2343
+ if (!(0, import_fs12.existsSync)(packageJsonPath) || !(0, import_fs12.existsSync)(templatePackageJsonPath))
1407
2344
  return;
1408
- let packageJsonContent = await (0, import_promises3.readFile)(packageJsonPath, "utf-8"), templatePackageJsonRaw = await (0, import_promises3.readFile)(templatePackageJsonPath), templatePackageJsonContent = applySubstitutions2(
2345
+ let packageJsonContent = await (0, import_promises4.readFile)(packageJsonPath, "utf-8"), templatePackageJsonRaw = await (0, import_promises4.readFile)(templatePackageJsonPath), templatePackageJsonContent = applySubstitutions2(
1409
2346
  "package.json",
1410
2347
  templatePackageJsonRaw
1411
2348
  ).toString("utf8"), packageJson = JSON.parse(packageJsonContent), templatePackageJson = JSON.parse(templatePackageJsonContent), updated = !1;
1412
2349
  dependencies.forEach((dep) => {
1413
2350
  packageJson.dependencies?.[dep] && templatePackageJson.dependencies?.[dep] && packageJson.dependencies[dep] !== templatePackageJson.dependencies[dep] && (packageJson.dependencies[dep] = templatePackageJson.dependencies[dep], updated = !0);
1414
- }), updated && await (0, import_promises3.writeFile)(packageJsonPath, JSON.stringify(packageJson, null, 4) + `
2351
+ }), updated && await (0, import_promises4.writeFile)(packageJsonPath, JSON.stringify(packageJson, null, 4) + `
1415
2352
  `, "utf-8");
1416
2353
  };
1417
2354
 
@@ -1422,34 +2359,25 @@ async function up() {
1422
2359
  }
1423
2360
 
1424
2361
  // src/utils/getVersion.ts
1425
- var import_fs9 = require("fs"), import_path9 = require("path"), UNKNOWN_VERSION = "unknown", getVersionFromPackageJson = () => {
1426
- try {
1427
- let packagePath = (0, import_path9.resolve)(__dirname, "../../package.json");
1428
- return (0, import_fs9.existsSync)(packagePath) && JSON.parse((0, import_fs9.readFileSync)(packagePath, "utf-8")).version || null;
1429
- } catch {
1430
- return null;
2362
+ var import_fs13 = require("fs"), import_path13 = require("path"), UNKNOWN_VERSION = "unknown", CANDIDATES = ["..", "../.."], findVersionInPackageJson = (startDir) => {
2363
+ for (let rel of CANDIDATES) {
2364
+ let path18 = (0, import_path13.resolve)(startDir, rel, "package.json");
2365
+ if ((0, import_fs13.existsSync)(path18))
2366
+ try {
2367
+ let pkg = JSON.parse((0, import_fs13.readFileSync)(path18, "utf-8"));
2368
+ if (typeof pkg.version == "string") return pkg.version;
2369
+ } catch {
2370
+ }
1431
2371
  }
1432
- }, getVersion = () => "0.3.0";
2372
+ return null;
2373
+ }, getVersion = () => findVersionInPackageJson(__dirname) ?? UNKNOWN_VERSION;
1433
2374
 
1434
2375
  // src/index.ts
1435
2376
  init_verbose();
1436
-
1437
- // src/utils/withErrorHandling.ts
1438
- init_logger();
1439
- function withErrorHandling(fn) {
1440
- return async (...args) => {
1441
- try {
1442
- await fn(...args);
1443
- } catch (error2) {
1444
- error2 instanceof Error && error2.name === "ExitPromptError" && process.exit(0), logger_default.error(error2), process.exit(1);
1445
- }
1446
- };
1447
- }
1448
-
1449
- // src/index.ts
2377
+ init_withErrorHandling();
1450
2378
  async function main() {
1451
- let program = new import_commander.Command(), version = getVersion();
1452
- await checkUpdate(version), program.name(CLI_NAME2).description(CLI_DESCRIPTION2).version(version), CLI_HELP_TEXT2 && program.addHelpText("before", CLI_HELP_TEXT2), program.hook("preAction", (thisCommand) => {
2379
+ let program = new import_commander2.Command(), version = getVersion();
2380
+ 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) => {
1453
2381
  setVerboseEnabled(!!thisCommand.opts().verbose);
1454
2382
  }), 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(
1455
2383
  "start a tunnel to connect your local code with the app running in the development environment"