@weavix/cli 0.2.0-dev → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.js CHANGED
@@ -47,14 +47,10 @@ function setVerboseEnabled(value) {
47
47
  function isVerboseEnabled() {
48
48
  return verboseEnabled;
49
49
  }
50
- function writeVerboseArtifact(relativePath, content) {
51
- let targetPath = import_path.default.resolve(".tracker-cli-debug", relativePath);
52
- return import_fs.default.mkdirSync(import_path.default.dirname(targetPath), { recursive: !0 }), import_fs.default.writeFileSync(targetPath, content), targetPath;
53
- }
54
- var import_fs, import_path, verboseEnabled, init_verbose = __esm({
50
+ var verboseEnabled, init_verbose = __esm({
55
51
  "src/utils/verbose.ts"() {
56
52
  "use strict";
57
- import_fs = __toESM(require("fs")), import_path = __toESM(require("path")), verboseEnabled = !1;
53
+ verboseEnabled = !1;
58
54
  }
59
55
  });
60
56
 
@@ -109,94 +105,77 @@ var import_picocolors, logger, logger_default, init_logger = __esm({
109
105
  }
110
106
  });
111
107
 
112
- // src/distributions/external/config/configManager.ts
108
+ // src/core/cliConfig/manager.ts
113
109
  function getConfigPath() {
114
110
  return CONFIG_FILE;
115
111
  }
116
112
  function readConfig() {
117
113
  if (cached !== void 0)
118
114
  return cached;
119
- if (!(0, import_fs2.existsSync)(CONFIG_FILE))
115
+ if (!(0, import_fs.existsSync)(CONFIG_FILE))
120
116
  return cached = null, cached;
121
117
  try {
122
- cached = JSON.parse((0, import_fs2.readFileSync)(CONFIG_FILE, "utf-8"));
118
+ cached = JSON.parse((0, import_fs.readFileSync)(CONFIG_FILE, "utf-8"));
123
119
  } catch {
124
120
  cached = null;
125
121
  }
126
122
  return cached;
127
123
  }
128
124
  function writeConfig(config) {
129
- (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;
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;
130
126
  }
131
127
  function clearConfig() {
132
- (0, import_fs2.existsSync)(CONFIG_FILE) && (0, import_fs2.rmSync)(CONFIG_FILE), cached = null;
128
+ (0, import_fs.existsSync)(CONFIG_FILE) && (0, import_fs.rmSync)(CONFIG_FILE), cached = null;
133
129
  }
134
- function requireConfig() {
135
- let config = readConfig();
136
- if (!config)
137
- throw new Error('CLI is not configured. Run "weavix config set" to configure.');
138
- return config;
139
- }
140
- var import_fs2, os, import_path2, CONFIG_DIR, CONFIG_FILE, cached, init_configManager = __esm({
141
- "src/distributions/external/config/configManager.ts"() {
130
+ var import_fs, os, import_path, CONFIG_DIR, CONFIG_FILE, cached, init_manager = __esm({
131
+ "src/core/cliConfig/manager.ts"() {
142
132
  "use strict";
143
- 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");
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");
144
134
  }
145
135
  });
146
136
 
147
- // src/distributions/external/config/index.ts
148
- async function promptString(message, current, required = !0) {
137
+ // src/core/cliConfig/registerCommand.ts
138
+ async function promptString(message, current) {
149
139
  return (await (0, import_prompts.input)({
150
- message: current ? `${message} (current: ${current})` : message,
140
+ message: current ? `${message} (current: ${current})` : `${message} (optional)`,
151
141
  default: current,
152
- required: required && !current
142
+ required: !1
153
143
  }))?.trim() || void 0;
154
144
  }
155
- async function runConfigSet() {
145
+ async function runConfigSet(cliName) {
156
146
  let existing = readConfig() ?? {};
157
- logger_default.info("Configure CLI endpoints. Empty input keeps the current value.");
158
- let s3Endpoint = await promptString("S3 endpoint", existing.s3?.endpoint), s3Region = await promptString("S3 region", existing.s3?.region), mdsEndpoint = await promptString("MDS endpoint", existing.mds?.endpoint), testingStatic = await promptString(
159
- "Testing bucket (static)",
160
- existing.buckets?.testing?.static
161
- ), testingConfig = await promptString(
162
- "Testing bucket (config)",
163
- existing.buckets?.testing?.config
164
- ), productionStatic = await promptString(
147
+ logger_default.info(
148
+ "Configure CLI overrides. Empty input clears the value (and falls back to defaults where applicable)."
149
+ );
150
+ let s3Endpoint = await promptString("S3 endpoint", existing.s3?.endpoint), s3Region = await promptString("S3 region", existing.s3?.region), mdsEndpoint = await promptString("MDS endpoint", existing.mds?.endpoint), productionStatic = await promptString(
165
151
  "Production bucket (static)",
166
152
  existing.buckets?.production?.static
167
153
  ), productionConfig = await promptString(
168
154
  "Production bucket (config)",
169
155
  existing.buckets?.production?.config
170
- ), pluginDownloadTesting = await promptString(
171
- "Plugin download base URL (testing)",
172
- existing.pluginDownloadBase?.testing
173
156
  ), pluginDownloadProduction = await promptString(
174
- "Plugin download base URL (production)",
157
+ "Plugin download base URL",
175
158
  existing.pluginDownloadBase?.production
176
159
  ), platformBaseUrl = await promptString(
177
160
  "Platform API base URL",
178
161
  existing.api?.platformBaseUrl
179
- ), trackerBaseUrl = await promptString("Tracker API base URL", existing.api?.trackerBaseUrl), oauthUrl = await promptString("OAuth token URL", existing.auth?.oauthUrl);
162
+ ), oauthUrl = await promptString("OAuth token URL", existing.auth?.oauthUrl);
180
163
  writeConfig({
181
164
  s3: { endpoint: s3Endpoint, region: s3Region },
182
165
  mds: { endpoint: mdsEndpoint },
183
166
  buckets: {
184
- testing: { static: testingStatic, config: testingConfig },
185
167
  production: { static: productionStatic, config: productionConfig }
186
168
  },
187
- pluginDownloadBase: {
188
- testing: pluginDownloadTesting,
189
- production: pluginDownloadProduction
190
- },
191
- api: { platformBaseUrl, trackerBaseUrl },
169
+ pluginDownloadBase: { production: pluginDownloadProduction },
170
+ api: { platformBaseUrl },
192
171
  auth: { oauthUrl }
193
- }), logger_default.success(`Configuration saved \u2192 ${getConfigPath()}`);
172
+ }), logger_default.success(`Configuration saved \u2192 ${getConfigPath()}`), logger_default.info(`Inspect with "${cliName} config show" or revert with "${cliName} config clear".`);
194
173
  }
195
- function runConfigShow() {
174
+ function runConfigShow(cliName) {
196
175
  let cfg = readConfig();
197
176
  if (!cfg) {
198
177
  logger_default.info(
199
- `No configuration found at ${getConfigPath()}. Run "weavix config set" to create one.`
178
+ `No configuration found at ${getConfigPath()}. Run "${cliName} config set" to create one.`
200
179
  );
201
180
  return;
202
181
  }
@@ -205,16 +184,16 @@ function runConfigShow() {
205
184
  function runConfigClear() {
206
185
  clearConfig(), logger_default.success(`Configuration removed (${getConfigPath()})`);
207
186
  }
208
- function registerConfigCommand(program) {
187
+ function registerConfigCommand(program, cliName) {
209
188
  let config = program.command("config").description("manage CLI configuration");
210
- config.command("set").description("set CLI configuration values interactively").action(runConfigSet), config.command("show").description("display current CLI configuration").action(runConfigShow), config.command("clear").description("remove stored CLI configuration").action(runConfigClear);
189
+ config.command("set").description("set CLI configuration values interactively").action(() => runConfigSet(cliName)), config.command("show").description("display current CLI configuration").action(() => runConfigShow(cliName)), config.command("clear").description("remove stored CLI configuration").action(runConfigClear);
211
190
  }
212
- var import_prompts, init_config = __esm({
213
- "src/distributions/external/config/index.ts"() {
191
+ var import_prompts, init_registerCommand = __esm({
192
+ "src/core/cliConfig/registerCommand.ts"() {
214
193
  "use strict";
215
194
  import_prompts = require("@inquirer/prompts");
216
195
  init_logger();
217
- init_configManager();
196
+ init_manager();
218
197
  }
219
198
  });
220
199
 
@@ -224,12 +203,13 @@ __export(registerCommands_exports, {
224
203
  registerDistributionCommands: () => registerDistributionCommands
225
204
  });
226
205
  function registerDistributionCommands(program) {
227
- registerConfigCommand(program);
206
+ registerConfigCommand(program, CLI_NAME);
228
207
  }
229
208
  var init_registerCommands = __esm({
230
209
  "src/distributions/external/registerCommands.ts"() {
231
210
  "use strict";
232
- init_config();
211
+ init_registerCommand();
212
+ init_meta();
233
213
  }
234
214
  });
235
215
 
@@ -246,6 +226,12 @@ __export(hosts_exports, {
246
226
  getTrackerBaseUrl: () => getTrackerBaseUrl,
247
227
  getUpdateCheckInfo: () => getUpdateCheckInfo
248
228
  });
229
+ function requireConfig() {
230
+ let cfg = readConfig();
231
+ if (!cfg)
232
+ throw new Error('CLI is not configured. Run "weavix config set" to configure.');
233
+ return cfg;
234
+ }
249
235
  function getS3Endpoint() {
250
236
  let cfg = requireConfig();
251
237
  if (!cfg.s3?.endpoint)
@@ -265,19 +251,19 @@ function getS3Region() {
265
251
  return cfg.s3.region;
266
252
  }
267
253
  function getBuckets() {
268
- let buckets = requireConfig().buckets, testing = buckets?.testing, production = buckets?.production;
269
- if (!testing?.static || !testing?.config || !production?.static || !production?.config)
254
+ let production = requireConfig().buckets?.production;
255
+ if (!production?.static || !production?.config)
270
256
  throw new Error('S3 buckets are not configured. Run "weavix config set" to configure.');
271
- return {
272
- testing: { static: testing.static, config: testing.config },
273
- production: { static: production.static, config: production.config }
274
- };
257
+ let prod = { static: production.static, config: production.config };
258
+ return { testing: prod, production: prod };
275
259
  }
276
260
  function getPluginDownloadBase(env) {
277
- let base = requireConfig().pluginDownloadBase?.[env];
261
+ if (env === "debug")
262
+ return "http://localhost:5173/plugins-debug";
263
+ let base = requireConfig().pluginDownloadBase?.production;
278
264
  if (!base)
279
265
  throw new Error(
280
- `Plugin download base for "${env}" is not configured. Run "weavix config set" to configure.`
266
+ 'Plugin download base is not configured. Run "weavix config set" to configure.'
281
267
  );
282
268
  return base;
283
269
  }
@@ -290,10 +276,7 @@ function getPlatformBaseUrl() {
290
276
  return cfg.api.platformBaseUrl;
291
277
  }
292
278
  function getTrackerBaseUrl() {
293
- let cfg = requireConfig();
294
- if (!cfg.api?.trackerBaseUrl)
295
- throw new Error('Tracker API URL is not configured. Run "weavix config set" to configure.');
296
- return cfg.api.trackerBaseUrl;
279
+ return TRACKER_BASE_URL;
297
280
  }
298
281
  function getOAuthTokenUrl() {
299
282
  let cfg = requireConfig();
@@ -304,10 +287,86 @@ function getOAuthTokenUrl() {
304
287
  function getUpdateCheckInfo() {
305
288
  return null;
306
289
  }
307
- var init_hosts = __esm({
290
+ var TRACKER_BASE_URL, init_hosts = __esm({
308
291
  "src/distributions/external/hosts.ts"() {
309
292
  "use strict";
310
- init_configManager();
293
+ init_manager();
294
+ TRACKER_BASE_URL = "https://tracker.yandex.ru";
295
+ }
296
+ });
297
+
298
+ // src/distributions/external/templateSubstitution.ts
299
+ var templateSubstitution_exports = {};
300
+ __export(templateSubstitution_exports, {
301
+ applySubstitutions: () => applySubstitutions,
302
+ templateDeps: () => templateDeps
303
+ });
304
+ function rewritePackageJson(content) {
305
+ let pkg = JSON.parse(content);
306
+ if (pkg.dependencies) {
307
+ let next = {};
308
+ for (let [name, version] of Object.entries(pkg.dependencies)) {
309
+ if (PACKAGE_DROP.has(name))
310
+ continue;
311
+ let renamed = PACKAGE_RENAME[name] ?? name;
312
+ next[renamed] = ADDED_DEPS[renamed] ?? version;
313
+ }
314
+ for (let [name, version] of Object.entries(ADDED_DEPS))
315
+ name in next || (next[name] = version);
316
+ pkg.dependencies = Object.fromEntries(
317
+ Object.entries(next).sort(([a], [b]) => a.localeCompare(b))
318
+ );
319
+ }
320
+ return JSON.stringify(pkg, null, 4) + `
321
+ `;
322
+ }
323
+ function rewriteImports(content) {
324
+ let result = content;
325
+ for (let [from, to] of Object.entries(PACKAGE_RENAME)) {
326
+ let escaped = from.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
327
+ result = result.replace(new RegExp(escaped, "g"), to);
328
+ }
329
+ return result;
330
+ }
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
+ function rewriteNpmrc(content) {
340
+ return content.split(`
341
+ `).filter((line) => !/^registry\s*=\s*https?:\/\/npm\.yandex-team\.ru/.test(line.trim())).join(`
342
+ `);
343
+ }
344
+ function applySubstitutions(filePath, content) {
345
+ let name = import_path2.default.basename(filePath), ext = import_path2.default.extname(filePath);
346
+ if (name === "package.json")
347
+ return Buffer.from(rewritePackageJson(content.toString("utf8")), "utf8");
348
+ if (name === "npmrc.template" || name === ".npmrc")
349
+ return Buffer.from(rewriteNpmrc(content.toString("utf8")), "utf8");
350
+ if (ext === ".scss" || ext === ".css")
351
+ return Buffer.from(rewriteScss(content.toString("utf8")), "utf8");
352
+ if ([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"].includes(ext)) {
353
+ let text = content.toString("utf8"), rewritten = rewriteImports(text);
354
+ if (rewritten !== text)
355
+ return Buffer.from(rewritten, "utf8");
356
+ }
357
+ return content;
358
+ }
359
+ var import_path2, PACKAGE_RENAME, PACKAGE_DROP, ADDED_DEPS, templateDeps, init_templateSubstitution = __esm({
360
+ "src/distributions/external/templateSubstitution.ts"() {
361
+ "use strict";
362
+ import_path2 = __toESM(require("path")), PACKAGE_RENAME = {
363
+ "@yandex-data-ui/tracker-plugin-sdk-react": "@weavix/sdk-react",
364
+ "@yandex-data-ui/tracker-pub-api-types": "@weavix/tracker-api-types"
365
+ }, PACKAGE_DROP = /* @__PURE__ */ new Set(["@yandex-data-ui/gravity-themes"]), ADDED_DEPS = {
366
+ "@weavix/sdk-core": "latest",
367
+ "@weavix/sdk-react": "latest",
368
+ "@weavix/tracker-api-types": "latest"
369
+ }, templateDeps = ["@weavix/sdk-core", "@weavix/sdk-react", "@weavix/tracker-api-types"];
311
370
  }
312
371
  });
313
372
 
@@ -339,16 +398,16 @@ var impl3 = (init_hosts(), __toCommonJS(hosts_exports)), {
339
398
  // src/utils/checkUpdate.ts
340
399
  init_logger();
341
400
  var checkUpdate = async (version) => {
342
- let info3 = getUpdateCheckInfo2();
343
- if (info3)
401
+ let info2 = getUpdateCheckInfo2();
402
+ if (info2)
344
403
  try {
345
- let response = await (0, import_node_fetch.default)(`${info3.registryUrl}/${info3.packageName}/latest`);
404
+ let response = await (0, import_node_fetch.default)(`${info2.registryUrl}/${info2.packageName}/latest`);
346
405
  if (!response.ok)
347
406
  return;
348
407
  let latest = await response.json();
349
408
  latest.version !== version && (logger_default.newLine(), logger_default.info(
350
409
  `\u{1F514} Update available ${version} \u2192 ${latest.version}
351
- Run: npm i -g ${info3.packageName}@latest --registry=${info3.registryUrl}`
410
+ Run: npm i -g ${info2.packageName}@latest --registry=${info2.registryUrl}`
352
411
  ));
353
412
  } catch {
354
413
  }
@@ -469,7 +528,6 @@ var TEMPLATES = [
469
528
  "project.action",
470
529
  "portfolio.action",
471
530
  "goal.action",
472
- "issue.floatingbottom.action",
473
531
  "attachment.viewer.action"
474
532
  ];
475
533
  var TEMPLATE_SLOTS = {
@@ -483,7 +541,6 @@ var TEMPLATE_SLOTS = {
483
541
  "project.action": ["project.action"],
484
542
  "portfolio.action": ["portfolio.action"],
485
543
  "goal.action": ["goal.action"],
486
- "issue.floatingbottom.action": ["issue.floatingbottom.action"],
487
544
  "attachment.viewer.action": ["attachment.viewer.action"]
488
545
  };
489
546
 
@@ -500,7 +557,7 @@ ${import_picocolors2.default.dim("Press")} ${import_picocolors2.default.yellow("
500
557
  `;
501
558
 
502
559
  // src/commands/create/utils/initManifest.ts
503
- var fs2 = __toESM(require("fs")), path3 = __toESM(require("path"));
560
+ var fs = __toESM(require("fs")), path2 = __toESM(require("path"));
504
561
 
505
562
  // src/commands/create/utils/generateManifest.ts
506
563
  function buildSlots(template, slotTitle) {
@@ -535,15 +592,21 @@ var generateManifest = (answers) => ({
535
592
 
536
593
  // src/commands/create/utils/initManifest.ts
537
594
  var initManifest = ({ answers, targetDir }) => {
538
- let generatedManifest = generateManifest(answers), manifestPath2 = path3.join(targetDir, "manifest.json");
539
- fs2.writeFileSync(manifestPath2, JSON.stringify(generatedManifest, null, 2), "utf-8");
595
+ let generatedManifest = generateManifest(answers), manifestPath2 = path2.join(targetDir, "manifest.json");
596
+ fs.writeFileSync(manifestPath2, JSON.stringify(generatedManifest, null, 2), "utf-8");
540
597
  };
541
598
 
542
599
  // src/commands/create/utils/initTemplate.ts
543
- var fs5 = __toESM(require("fs")), path7 = __toESM(require("path"));
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");
604
+
605
+ // src/distribution/templateSubstitution.ts
606
+ var impl4 = (init_templateSubstitution(), __toCommonJS(templateSubstitution_exports)), { applySubstitutions: applySubstitutions2, templateDeps: templateDeps2 } = impl4;
544
607
 
545
608
  // src/utils/copyDirectory.ts
546
- var fs3 = __toESM(require("fs")), import_path3 = __toESM(require("path")), import_tinyglobby = require("tinyglobby"), resolveTargetFileName = (file) => file.endsWith(".template") ? "." + file.replace(".template", "") : file, copyDirectory = async (sourceDir, targetDir) => {
609
+ var resolveTargetFileName = (file) => file.endsWith(".template") ? "." + file.replace(".template", "") : file, copyDirectory = async (sourceDir, targetDir) => {
547
610
  let files = await (0, import_tinyglobby.glob)(["**/*"], {
548
611
  cwd: sourceDir,
549
612
  onlyFiles: !0,
@@ -552,33 +615,32 @@ var fs3 = __toESM(require("fs")), import_path3 = __toESM(require("path")), impor
552
615
  await Promise.all(
553
616
  files.map(async (file) => {
554
617
  let sourcePath = import_path3.default.join(sourceDir, file), targetFile = resolveTargetFileName(file), targetPath = import_path3.default.join(targetDir, targetFile);
555
- await fs3.promises.mkdir(import_path3.default.dirname(targetPath), { recursive: !0 }), await fs3.promises.copyFile(sourcePath, targetPath);
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);
556
621
  })
557
622
  );
558
623
  };
559
624
 
560
625
  // src/utils/getProjectPath.ts
561
- var import_path4 = __toESM(require("path")), isDevelopment = () => __dirname.includes("/src/"), getProjectPath = (relativePath) => {
562
- let levelsUp = isDevelopment() ? "../.." : "..";
563
- return import_path4.default.resolve(__dirname, levelsUp, relativePath);
564
- }, getTemplatesBaseDir = () => getProjectPath("templates"), getTemplatePath = (filename) => import_path4.default.join(getTemplatesBaseDir(), "_shared", filename);
626
+ var import_path4 = __toESM(require("path")), isDevelopment = () => __dirname.includes("/src/"), getProjectPath = (relativePath) => isDevelopment() ? import_path4.default.resolve(__dirname, "..", "..", relativePath) : import_path4.default.resolve(__dirname, relativePath), getTemplatesBaseDir = () => getProjectPath("templates"), getTemplatePath = (filename) => import_path4.default.join(getTemplatesBaseDir(), "_shared", filename);
565
627
 
566
628
  // src/commands/create/utils/initTemplate.ts
567
629
  init_logger();
568
630
 
569
631
  // src/commands/create/utils/updatePackageJson.ts
570
- var fs4 = __toESM(require("fs")), path6 = __toESM(require("path")), updatePackageJson = (targetDir, packageSlug) => {
632
+ var fs3 = __toESM(require("fs")), path6 = __toESM(require("path")), updatePackageJson = (targetDir, packageSlug) => {
571
633
  let packageJsonPath = path6.join(targetDir, "package.json");
572
- if (fs4.existsSync(packageJsonPath)) {
573
- let packageJson = JSON.parse(fs4.readFileSync(packageJsonPath, "utf-8"));
574
- packageJson.name = packageSlug, fs4.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 4) + `
634
+ if (fs3.existsSync(packageJsonPath)) {
635
+ let packageJson = JSON.parse(fs3.readFileSync(packageJsonPath, "utf-8"));
636
+ packageJson.name = packageSlug, fs3.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 4) + `
575
637
  `);
576
638
  }
577
639
  };
578
640
 
579
641
  // src/commands/create/utils/initTemplate.ts
580
642
  var initTemplate = async ({ answers, targetDir }) => {
581
- fs5.existsSync(targetDir) || fs5.mkdirSync(targetDir, { recursive: !0 });
643
+ fs4.existsSync(targetDir) || fs4.mkdirSync(targetDir, { recursive: !0 });
582
644
  let templatesBaseDir = getTemplatesBaseDir(), templatesDir = path7.join(templatesBaseDir, answers.template), sharedDir = path7.join(templatesBaseDir, "_shared");
583
645
  await copyDirectory(sharedDir, targetDir), await copyDirectory(templatesDir, targetDir), updatePackageJson(targetDir, answers.packageSlug), logger_default.info("Created template with marketplace publication requirements."), logger_default.info(
584
646
  "Before publishing, add ./marketplace/index.md, ./marketplace/header-image.jpg (784:325), and ./public/logo.svg (square)."
@@ -635,15 +697,15 @@ async function create() {
635
697
  }), logger_default.newLine(), logger_default.success("Package generated!"), logger_default.commands("To get started, run", [
636
698
  `cd ${answers.packageSlug}`,
637
699
  "npm install",
638
- "tracker-cli debug"
700
+ `${CLI_NAME2} debug`
639
701
  ]);
640
702
  }
641
703
 
642
704
  // src/commands/debug/index.ts
643
- var import_fs7 = __toESM(require("fs")), import_path8 = __toESM(require("path"));
705
+ var import_fs6 = __toESM(require("fs")), import_path8 = __toESM(require("path"));
644
706
 
645
707
  // src/core/manifest/manifestManager.ts
646
- var import_fs3 = require("fs"), import_promises = require("fs/promises"), import_ajv = __toESM(require("ajv")), import_ajv_formats = __toESM(require("ajv-formats"));
708
+ var import_fs2 = require("fs"), import_promises = require("fs/promises"), import_ajv = __toESM(require("ajv")), import_ajv_formats = __toESM(require("ajv-formats"));
647
709
 
648
710
  // src/core/manifest/formatValidationErrors.ts
649
711
  var priorityOrder = [
@@ -670,14 +732,14 @@ var priorityOrder = [
670
732
  }, formatValidationErrors = (errors) => {
671
733
  let errorsByPath = {};
672
734
  for (let error2 of errors) {
673
- let path18 = error2.instancePath || "root";
674
- errorsByPath[path18] || (errorsByPath[path18] = []), errorsByPath[path18].push(error2);
735
+ let path13 = error2.instancePath || "root";
736
+ errorsByPath[path13] || (errorsByPath[path13] = []), errorsByPath[path13].push(error2);
675
737
  }
676
- return Object.entries(errorsByPath).map(([path18, pathErrors]) => {
738
+ return Object.entries(errorsByPath).map(([path13, pathErrors]) => {
677
739
  let error2 = [...pathErrors].sort(
678
740
  (a, b) => getPriority(a.keyword) - getPriority(b.keyword)
679
741
  )[0], formatter = errorMessages[error2.keyword], message = formatter ? formatter(error2.params) : error2.message;
680
- return ` - ${path18}: ${message}`;
742
+ return ` - ${path13}: ${message}`;
681
743
  }).join(`
682
744
  `);
683
745
  };
@@ -1052,14 +1114,6 @@ var manifest_schema_default = {
1052
1114
  $ref: "#/definitions/SlotConfig"
1053
1115
  }
1054
1116
  },
1055
- "issue.floatingbottom.action": {
1056
- type: "array",
1057
- description: "Issue Floatingbottom Action slot configurations",
1058
- minItems: 1,
1059
- items: {
1060
- $ref: "#/definitions/SlotConfig"
1061
- }
1062
- },
1063
1117
  "attachment.viewer.action": {
1064
1118
  type: "array",
1065
1119
  description: "Attachment Viewer Action slot configurations",
@@ -1155,7 +1209,7 @@ var validator = (() => {
1155
1209
  }
1156
1210
  return manifest;
1157
1211
  }, loadRaw = async () => {
1158
- if (!(0, import_fs3.existsSync)(manifestPath))
1212
+ if (!(0, import_fs2.existsSync)(manifestPath))
1159
1213
  throw new Error(`File manifest.json not found at path: ${manifestPath}`);
1160
1214
  try {
1161
1215
  return await (0, import_promises.readFile)(manifestPath, "utf8");
@@ -1191,23 +1245,7 @@ ${errorMessages2}`);
1191
1245
  };
1192
1246
 
1193
1247
  // src/core/s3config/constants.ts
1194
- var CONFIG_FILE_NAME = "config.json", DEFAULT_ENVIRONMENT = "production", mimeTypes = {
1195
- ".html": "text/html",
1196
- ".css": "text/css",
1197
- ".js": "text/javascript",
1198
- ".json": "application/json",
1199
- ".png": "image/png",
1200
- ".jpg": "image/jpeg",
1201
- ".jpeg": "image/jpeg",
1202
- ".gif": "image/gif",
1203
- ".svg": "image/svg+xml",
1204
- ".ico": "image/x-icon",
1205
- ".txt": "text/plain",
1206
- ".woff": "font/woff",
1207
- ".woff2": "font/woff2",
1208
- ".ttf": "font/ttf",
1209
- ".eot": "application/vnd.ms-fontobject"
1210
- };
1248
+ var CONFIG_FILE_NAME = "config.json";
1211
1249
 
1212
1250
  // src/commands/debug/index.ts
1213
1251
  init_logger();
@@ -1222,11 +1260,11 @@ var registerCleanup = (cleanup) => {
1222
1260
  };
1223
1261
 
1224
1262
  // src/commands/debug/utils/createDebugConfig.ts
1225
- var import_fs4 = __toESM(require("fs")), import_path5 = __toESM(require("path"));
1263
+ var import_fs3 = __toESM(require("fs")), import_path5 = __toESM(require("path"));
1226
1264
 
1227
1265
  // src/utils/convertManifestToConfig.ts
1228
1266
  function buildPluginDownloadUrl(env, id, version) {
1229
- return `${getPluginDownloadBase2(env)}/${id}/${version}`;
1267
+ return env === "debug" ? getPluginDownloadBase2(env) : `${getPluginDownloadBase2(env)}/${id}/${version}`;
1230
1268
  }
1231
1269
  var convertManifestToConfig = (manifest, environment) => {
1232
1270
  let config = {};
@@ -1268,20 +1306,20 @@ var convertManifestToConfig = (manifest, environment) => {
1268
1306
  // src/commands/debug/utils/createDebugConfig.ts
1269
1307
  var createDebugConfig = async () => {
1270
1308
  let manifest = await manifestManager.load(), config = convertManifestToConfig(manifest, "debug"), configPath = import_path5.default.join(process.cwd(), CONFIG_FILE_NAME);
1271
- import_fs4.default.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
1309
+ import_fs3.default.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
1272
1310
  };
1273
1311
 
1274
1312
  // src/commands/debug/utils/lockFile.ts
1275
- var import_fs5 = __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 = () => {
1313
+ 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 = () => {
1276
1314
  let lockPath = getLockFilePath();
1277
- if (!import_fs5.default.existsSync(lockPath))
1315
+ if (!import_fs4.default.existsSync(lockPath))
1278
1316
  return null;
1279
1317
  try {
1280
- let pid = JSON.parse(import_fs5.default.readFileSync(lockPath, "utf-8")).pid;
1318
+ let pid = JSON.parse(import_fs4.default.readFileSync(lockPath, "utf-8")).pid;
1281
1319
  return process.kill(pid, 0), pid;
1282
1320
  } catch {
1283
1321
  try {
1284
- import_fs5.default.unlinkSync(lockPath);
1322
+ import_fs4.default.unlinkSync(lockPath);
1285
1323
  } catch {
1286
1324
  }
1287
1325
  return null;
@@ -1289,18 +1327,18 @@ var import_fs5 = __toESM(require("fs")), import_path6 = __toESM(require("path"))
1289
1327
  }, createLockFile = () => {
1290
1328
  let lockPath = getLockFilePath(), lockData = {
1291
1329
  pid: process.pid
1292
- }, fd = import_fs5.default.openSync(lockPath, "wx");
1293
- import_fs5.default.writeSync(fd, JSON.stringify(lockData, null, 2)), import_fs5.default.closeSync(fd);
1330
+ }, fd = import_fs4.default.openSync(lockPath, "wx");
1331
+ import_fs4.default.writeSync(fd, JSON.stringify(lockData, null, 2)), import_fs4.default.closeSync(fd);
1294
1332
  }, removeLockFile = () => {
1295
1333
  let lockPath = getLockFilePath();
1296
- import_fs5.default.existsSync(lockPath) && import_fs5.default.unlinkSync(lockPath);
1334
+ import_fs4.default.existsSync(lockPath) && import_fs4.default.unlinkSync(lockPath);
1297
1335
  };
1298
1336
 
1299
1337
  // src/commands/debug/utils/watchManifest.ts
1300
- var import_fs6 = __toESM(require("fs")), import_path7 = __toESM(require("path"));
1338
+ var import_fs5 = __toESM(require("fs")), import_path7 = __toESM(require("path"));
1301
1339
  init_logger();
1302
1340
  var watchManifest = () => {
1303
- let manifestPath2 = import_path7.default.join(process.cwd(), "manifest.json"), debounceTimer = null, watcher = import_fs6.default.watch(manifestPath2, async (eventType) => {
1341
+ let manifestPath2 = import_path7.default.join(process.cwd(), "manifest.json"), debounceTimer = null, watcher = import_fs5.default.watch(manifestPath2, async (eventType) => {
1304
1342
  eventType === "change" && (debounceTimer && clearTimeout(debounceTimer), debounceTimer = setTimeout(async () => {
1305
1343
  try {
1306
1344
  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");
@@ -1318,7 +1356,7 @@ var watchManifest = () => {
1318
1356
  async function debug(options) {
1319
1357
  let runningPid = getRunningDebugPid();
1320
1358
  runningPid && (logger_default.error(
1321
- `Another instance of tracker-cli debug is already running.
1359
+ `Another instance of ${CLI_NAME2} debug is already running.
1322
1360
  Please stop the existing instance before starting a new one.
1323
1361
 
1324
1362
  If you lost the terminal tab, you can kill the process with:
@@ -1327,785 +1365,27 @@ If you lost the terminal tab, you can kill the process with:
1327
1365
  let configPath = import_path8.default.join(process.cwd(), CONFIG_FILE_NAME);
1328
1366
  options.lint && await manifestManager.validate(), await createDebugConfig();
1329
1367
  let watcher = watchManifest(), cleanup = () => {
1330
- watcher.close(), import_fs7.default.existsSync(configPath) && import_fs7.default.unlinkSync(configPath), removeLockFile();
1368
+ watcher.close(), import_fs6.default.existsSync(configPath) && import_fs6.default.unlinkSync(configPath), removeLockFile();
1331
1369
  };
1332
1370
  registerCleanup(cleanup), createLockFile(), await execCommand(pluginCmd.dev), cleanup();
1333
1371
  }
1334
1372
 
1335
- // src/core/s3config/promptEnvironment.ts
1336
- var import_prompts3 = require("@inquirer/prompts");
1337
- async function promptEnvironment() {
1338
- return await (0, import_prompts3.select)({
1339
- message: "Select environment:",
1340
- choices: [
1341
- { name: "Testing", value: "testing" },
1342
- { name: "Production", value: "production" }
1343
- ],
1344
- default: "testing"
1345
- });
1346
- }
1347
-
1348
- // src/core/s3config/s3Manager.ts
1349
- var import_fs8 = require("fs"), import_promises2 = require("fs/promises"), os2 = __toESM(require("os")), import_path9 = __toESM(require("path")), import_client_s3 = require("@aws-sdk/client-s3"), import_lib_storage = require("@aws-sdk/lib-storage"), import_tinyglobby2 = require("tinyglobby");
1350
- init_logger();
1351
-
1352
- // src/core/s3config/promptCredentials.ts
1353
- var import_prompts4 = require("@inquirer/prompts"), promptS3Credentials = async () => {
1354
- let s3AccessKeyId = await (0, import_prompts4.input)({
1355
- message: "Enter S3_ACCESS_KEY_ID:",
1356
- required: !0
1357
- }), s3SecretAccessKey = await (0, import_prompts4.input)({
1358
- message: "Enter S3_SECRET_ACCESS_KEY:",
1359
- required: !0
1360
- });
1361
- return {
1362
- s3AccessKeyId: s3AccessKeyId?.trim(),
1363
- s3SecretAccessKey: s3SecretAccessKey?.trim()
1364
- };
1365
- }, promptMdsCredentials = async () => {
1366
- let mdsAccessKeyId = await (0, import_prompts4.input)({
1367
- message: "Enter MDS_ACCESS_KEY_ID:",
1368
- required: !0
1369
- }), mdsSecretAccessKey = await (0, import_prompts4.input)({
1370
- message: "Enter MDS_SECRET_ACCESS_KEY:",
1371
- required: !0
1372
- });
1373
- return {
1374
- mdsAccessKeyId: mdsAccessKeyId?.trim(),
1375
- mdsSecretAccessKey: mdsSecretAccessKey?.trim()
1376
- };
1377
- };
1378
-
1379
- // src/core/s3config/s3Manager.ts
1380
- async function streamToBuffer(body) {
1381
- if (!body)
1382
- return Buffer.alloc(0);
1383
- let chunks = [];
1384
- for await (let chunk of body)
1385
- chunks.push(Buffer.from(chunk));
1386
- return Buffer.concat(chunks);
1387
- }
1388
- var S3Manager = class {
1389
- constructor() {
1390
- this.credentialsDir = import_path9.default.join(os2.homedir(), ".tracker-cli");
1391
- this.credentialsFile = import_path9.default.join(this.credentialsDir, "s3-credentials.json");
1392
- this._environment = DEFAULT_ENVIRONMENT;
1393
- }
1394
- setEnvironment(environment) {
1395
- this._environment = environment, logger_default.info(`Environment set to: ${environment}`);
1396
- }
1397
- async checkS3Auth() {
1398
- await this.checkAuth("s3");
1399
- }
1400
- async checkMdsAuth() {
1401
- await this.checkAuth("mds");
1402
- }
1403
- async saveCredentials(credentials) {
1404
- (0, import_fs8.existsSync)(this.credentialsDir) || (0, import_fs8.mkdirSync)(this.credentialsDir, { recursive: !0, mode: 448 }), await (0, import_promises2.writeFile)(this.credentialsFile, JSON.stringify(credentials, null, 2), {
1405
- mode: 384
1406
- });
1407
- }
1408
- get credentials() {
1409
- try {
1410
- if (!(0, import_fs8.existsSync)(this.credentialsFile))
1411
- return null;
1412
- let data = require("fs").readFileSync(this.credentialsFile, "utf-8");
1413
- return JSON.parse(data);
1414
- } catch {
1415
- return null;
1416
- }
1417
- }
1418
- async getPluginsConfig() {
1419
- let s3Client = this.createMdsS3Client(), bucket = this.getConfigBucket();
1420
- try {
1421
- let response = await s3Client.send(
1422
- new import_client_s3.GetObjectCommand({ Bucket: bucket, Key: CONFIG_FILE_NAME })
1423
- ), body = await streamToBuffer(response.Body);
1424
- return body.length ? JSON.parse(body.toString("utf8")) : (logger_default.info("NO DATA"), {});
1425
- } catch (error2) {
1426
- return logger_default.error("Error getting plugins config from S3", error2), process.exit();
1427
- }
1428
- }
1429
- async savePluginsConfig(config) {
1430
- let s3Client = this.createMdsS3Client(), bucket = this.getConfigBucket();
1431
- try {
1432
- await new import_lib_storage.Upload({
1433
- client: s3Client,
1434
- params: {
1435
- Bucket: bucket,
1436
- Key: CONFIG_FILE_NAME,
1437
- Body: Buffer.from(JSON.stringify(config), "utf8"),
1438
- ContentType: "application/json"
1439
- }
1440
- }).done();
1441
- } catch (error2) {
1442
- logger_default.error("Error writing plugins config to S3", error2), process.exit();
1443
- }
1444
- }
1445
- async uploadPluginFiles(manifest, files) {
1446
- if (files.length === 0) {
1447
- logger_default.warning("No files to upload in dist folder");
1448
- return;
1449
- }
1450
- let keyPrefix = `${manifest.slug}/${manifest.version}/`, s3Client = this.createAwsS3Client(), distPath = import_path9.default.resolve("./dist"), bucket = this.getStaticBucket();
1451
- logger_default.info(`\u{1F4E6} Starting file upload from ${distPath} to S3 bucket: ${bucket}`);
1452
- for (let filePath of files)
1453
- try {
1454
- let fileContent = await (0, import_promises2.readFile)(filePath), relativePath = import_path9.default.relative(distPath, filePath), s3Key = keyPrefix + relativePath.replace(/\\/g, "/"), mimeType = this.getMimeType(filePath);
1455
- logger_default.info(`\u2B06\uFE0F Uploading: ${relativePath}`), await new import_lib_storage.Upload({
1456
- client: s3Client,
1457
- params: {
1458
- Bucket: bucket,
1459
- Key: s3Key,
1460
- Body: fileContent,
1461
- ContentType: mimeType
1462
- }
1463
- }).done(), logger_default.success(`Uploaded: ${s3Key}`);
1464
- } catch (error2) {
1465
- logger_default.error(`Error uploading file ${filePath}`, error2), process.exit();
1466
- }
1467
- logger_default.success("Deployment completed successfully!");
1468
- }
1469
- /**
1470
- * Upload extra root-level files/directories to S3 under the same slug/version prefix.
1471
- * @param manifest slug + version for the key prefix
1472
- * @param rootPaths paths relative to cwd, e.g. ['manifest.json', 'marketplace']
1473
- */
1474
- async uploadRootFiles(manifest, rootPaths) {
1475
- let keyPrefix = `${manifest.slug}/${manifest.version}/`, s3Client = this.createAwsS3Client(), bucket = this.getStaticBucket(), cwd = process.cwd();
1476
- for (let rootPath of rootPaths) {
1477
- let absPath = import_path9.default.resolve(cwd, rootPath);
1478
- if (!(0, import_fs8.existsSync)(absPath)) {
1479
- logger_default.warning(`Skipping "${rootPath}" \u2014 not found`);
1480
- continue;
1481
- }
1482
- if ((await import("fs")).statSync(absPath).isFile()) {
1483
- let fileContent = await (0, import_promises2.readFile)(absPath), s3Key = keyPrefix + import_path9.default.basename(absPath), mimeType = this.getMimeType(absPath);
1484
- logger_default.info(`\u2B06\uFE0F Uploading: ${rootPath}`), await new import_lib_storage.Upload({
1485
- client: s3Client,
1486
- params: {
1487
- Bucket: bucket,
1488
- Key: s3Key,
1489
- Body: fileContent,
1490
- ContentType: mimeType
1491
- }
1492
- }).done(), logger_default.success(`Uploaded: ${s3Key}`);
1493
- } else {
1494
- let files = await (0, import_tinyglobby2.glob)(["**/*"], {
1495
- cwd: absPath,
1496
- onlyFiles: !0,
1497
- absolute: !0
1498
- });
1499
- for (let filePath of files)
1500
- try {
1501
- let fileContent = await (0, import_promises2.readFile)(filePath), relativePath = import_path9.default.relative(cwd, filePath), s3Key = keyPrefix + relativePath.replace(/\\/g, "/"), mimeType = this.getMimeType(filePath);
1502
- logger_default.info(`\u2B06\uFE0F Uploading: ${relativePath}`), await new import_lib_storage.Upload({
1503
- client: s3Client,
1504
- params: {
1505
- Bucket: bucket,
1506
- Key: s3Key,
1507
- Body: fileContent,
1508
- ContentType: mimeType
1509
- }
1510
- }).done(), logger_default.success(`Uploaded: ${s3Key}`);
1511
- } catch (error2) {
1512
- logger_default.error(`Error uploading file ${filePath}`, error2), process.exit();
1513
- }
1514
- }
1515
- }
1516
- }
1517
- createAwsS3Client() {
1518
- let credentials = this.credentials;
1519
- return (!credentials?.s3AccessKeyId || !credentials?.s3SecretAccessKey) && (logger_default.error("S3 credentials not found. Please log in using: tracker-cli login"), process.exit()), new import_client_s3.S3Client({
1520
- region: getS3Region2(),
1521
- endpoint: getS3Endpoint2(),
1522
- credentials: {
1523
- accessKeyId: credentials.s3AccessKeyId,
1524
- secretAccessKey: credentials.s3SecretAccessKey
1525
- }
1526
- });
1527
- }
1528
- async checkAuth(type) {
1529
- (type === "s3" ? await this.validateS3Credentials() : await this.validateMdsCredentials()) || (type === "s3" ? await this.promptS3CredentialsAndSave() : await this.promptMdsCredentialsAndSave());
1530
- }
1531
- async validateS3Credentials(credentials) {
1532
- let creds = credentials || this.credentials;
1533
- if (!creds || !creds.s3AccessKeyId || !creds.s3SecretAccessKey)
1534
- return !1;
1535
- try {
1536
- return await new import_client_s3.S3Client({
1537
- region: getS3Region2(),
1538
- endpoint: getS3Endpoint2(),
1539
- credentials: {
1540
- accessKeyId: creds.s3AccessKeyId,
1541
- secretAccessKey: creds.s3SecretAccessKey
1542
- }
1543
- }).send(new import_client_s3.ListBucketsCommand({})), !0;
1544
- } catch (error2) {
1545
- return logger_default.error("AWS S3 credential validation failed:", error2), !1;
1546
- }
1547
- }
1548
- async validateMdsCredentials(credentials) {
1549
- let creds = credentials || this.credentials;
1550
- if (!creds || !creds.mdsAccessKeyId || !creds.mdsSecretAccessKey)
1551
- return !1;
1552
- try {
1553
- let mdsClient = this.buildMdsS3Client(creds), bucket = this.getConfigBucket();
1554
- return await mdsClient.send(new import_client_s3.GetObjectCommand({ Bucket: bucket, Key: CONFIG_FILE_NAME })), !0;
1555
- } catch (error2) {
1556
- return logger_default.error("MDS credential validation failed:", error2), !1;
1557
- }
1558
- }
1559
- async promptS3CredentialsAndSave() {
1560
- await this.promptAndSaveCredentials(
1561
- "s3",
1562
- promptS3Credentials,
1563
- (creds) => this.validateS3Credentials(creds)
1564
- );
1565
- }
1566
- async promptMdsCredentialsAndSave() {
1567
- await this.promptAndSaveCredentials(
1568
- "mds",
1569
- promptMdsCredentials,
1570
- (creds) => this.validateMdsCredentials(creds)
1571
- );
1572
- }
1573
- async promptAndSaveCredentials(type, promptFn, validateFn) {
1574
- logger_default.info(`Please enter your ${type.toUpperCase()} credentials:`);
1575
- let newCreds = await promptFn(), updatedCreds = {
1576
- ...this.credentials || {},
1577
- ...newCreds
1578
- };
1579
- if (logger_default.info(`Validating ${type.toUpperCase()} credentials...`), !await validateFn(updatedCreds)) {
1580
- await this.promptAndSaveCredentials(type, promptFn, validateFn);
1581
- return;
1582
- }
1583
- await this.saveCredentials(updatedCreds), logger_default.success(`${type.toUpperCase()} credentials saved successfully.`);
1584
- }
1585
- getConfigBucket() {
1586
- return getBuckets2()[this._environment].config;
1587
- }
1588
- getStaticBucket() {
1589
- return getBuckets2()[this._environment].static;
1590
- }
1591
- createMdsS3Client() {
1592
- let credentials = this.credentials;
1593
- return (!credentials?.mdsAccessKeyId || !credentials?.mdsSecretAccessKey) && (logger_default.error("MdsS3 credentials not found. Please log in using: tracker-cli login"), process.exit()), this.buildMdsS3Client(credentials);
1594
- }
1595
- buildMdsS3Client(credentials) {
1596
- return new import_client_s3.S3Client({
1597
- region: getS3Region2(),
1598
- endpoint: getMdsEndpoint2(),
1599
- forcePathStyle: !0,
1600
- credentials: {
1601
- accessKeyId: credentials.mdsAccessKeyId,
1602
- secretAccessKey: credentials.mdsSecretAccessKey
1603
- }
1604
- });
1605
- }
1606
- getMimeType(filePath) {
1607
- let ext = import_path9.default.extname(filePath).toLowerCase();
1608
- return mimeTypes[ext] || "application/octet-stream";
1609
- }
1610
- }, s3Manager = new S3Manager();
1611
-
1612
- // src/utils/getFiles.ts
1613
- var import_fs9 = __toESM(require("fs")), import_path10 = __toESM(require("path")), import_tinyglobby3 = require("tinyglobby");
1614
- init_logger();
1615
- var getFiles = async () => {
1616
- let distPath = import_path10.default.resolve("./dist");
1617
- import_fs9.default.existsSync(distPath) || (logger_default.error("Dist folder not found. Build the project first"), process.exit());
1618
- let files = await (0, import_tinyglobby3.glob)(["**/*"], {
1619
- cwd: distPath,
1620
- onlyFiles: !0,
1621
- absolute: !0
1622
- });
1623
- return logger_default.info(`\u{1F4C1} Found ${files.length} files to upload`), files;
1624
- };
1625
-
1626
- // src/commands/deploy/index.ts
1627
- async function deploy() {
1628
- await s3Manager.checkS3Auth();
1629
- let environment = await promptEnvironment();
1630
- s3Manager.setEnvironment(environment);
1631
- let manifest = await manifestManager.load();
1632
- await build({ environment });
1633
- let files = await getFiles();
1634
- await s3Manager.uploadPluginFiles(manifest, files);
1635
- }
1636
-
1637
- // src/api/tracker.ts
1638
- var import_form_data = __toESM(require("form-data"));
1639
-
1640
- // src/api/trackerApiRequest.ts
1641
- var import_node_fetch2 = __toESM(require("node-fetch"));
1642
-
1643
- // src/core/auth/authManager.ts
1644
- var fs11 = __toESM(require("fs")), os3 = __toESM(require("os")), path15 = __toESM(require("path")), authDir = path15.join(os3.homedir(), ".tracker-cli"), authFile = path15.join(authDir, "auth.json"), getData = () => {
1645
- try {
1646
- if (!fs11.existsSync(authFile))
1647
- return null;
1648
- let data = fs11.readFileSync(authFile, "utf-8");
1649
- return JSON.parse(data);
1650
- } catch {
1651
- return null;
1652
- }
1653
- }, getAuthHeader = () => {
1654
- let authData = getData();
1655
- return authData ? `OAuth ${authData.token}` : null;
1656
- }, saveAuthData = (token) => {
1657
- let authData = {
1658
- token
1659
- };
1660
- fs11.existsSync(authDir) || fs11.mkdirSync(authDir, { recursive: !0, mode: 448 }), fs11.writeFileSync(authFile, JSON.stringify(authData, null, 2), {
1661
- mode: 384
1662
- });
1663
- }, removeAuthData = () => {
1664
- fs11.existsSync(authFile) && fs11.unlinkSync(authFile);
1665
- }, authManager = {
1666
- get authHeader() {
1667
- return getAuthHeader();
1668
- },
1669
- get data() {
1670
- return getData();
1671
- },
1672
- saveAuthData,
1673
- removeAuthData
1674
- };
1675
-
1676
- // src/api/trackerApiRequest.ts
1677
- function buildQueryString(queryParams) {
1678
- if (!queryParams || Object.keys(queryParams).length === 0)
1679
- return "";
1680
- let params = new URLSearchParams();
1681
- return Object.entries(queryParams).forEach(([key, value]) => {
1682
- params.append(key, String(value));
1683
- }), `?${params.toString()}`;
1684
- }
1685
- async function parseResponse(response) {
1686
- 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();
1687
- }
1688
- async function trackerApiRequest(endpoint, options = {}) {
1689
- let { method = "GET", body, headers = {}, formData, queryParams } = options, authHeader = authManager.authHeader;
1690
- if (!authHeader)
1691
- throw new Error('Not authenticated. Run "tracker-cli login" first.');
1692
- let requestHeaders = {
1693
- Authorization: authHeader,
1694
- Accept: "application/json",
1695
- ...headers
1696
- }, requestBody;
1697
- if (formData) {
1698
- let formHeaders = formData.getHeaders?.();
1699
- Object.assign(requestHeaders, formHeaders), requestBody = formData;
1700
- } else body && method !== "GET" && (requestHeaders["Content-Type"] = "application/json", requestBody = JSON.stringify(body));
1701
- let queryString = buildQueryString(queryParams), url = `${getTrackerBaseUrl2()}${endpoint}${queryString}`, response = await (0, import_node_fetch2.default)(url, {
1702
- method,
1703
- headers: requestHeaders,
1704
- body: requestBody
1705
- });
1706
- if (!response.ok) {
1707
- let errorText = await response.text(), errorMessage = `Tracker API error ${response.status}: ${errorText}`;
1708
- try {
1709
- let errorJson = JSON.parse(errorText);
1710
- errorJson.message && (errorMessage = `Tracker API error ${response.status}: ${errorJson.message}`);
1711
- } catch {
1712
- }
1713
- throw new Error(errorMessage);
1714
- }
1715
- return parseResponse(response);
1716
- }
1717
-
1718
- // src/api/tracker.ts
1719
- var PLUGINMOD_QUEUE = "PLUGINMOD";
1720
- function buildIssueSummary(slug) {
1721
- return `Plugin: ${slug}`;
1722
- }
1723
- function buildIssueDescription(params) {
1724
- let { pluginId, slug, version, manifestJson, catalogName, catalogDescription, catalogTags } = params, lines = [
1725
- `**Plugin UUID:** ${pluginId}`,
1726
- `**Slug:** ${slug}`,
1727
- `**Version:** ${version}`
1728
- ];
1729
- return catalogName && lines.push(`**Name:** ${catalogName}`), catalogDescription && lines.push(`**Description:** ${catalogDescription}`), catalogTags && catalogTags.length > 0 && lines.push(`**Tags:** ${catalogTags.join(", ")}`), lines.push("", "**Manifest:**", "```json", manifestJson, "```"), lines.join(`
1730
- `);
1731
- }
1732
- async function createPluginIssue(params) {
1733
- let { slug, pluginId, version, manifestJson } = params, body = {
1734
- queue: PLUGINMOD_QUEUE,
1735
- summary: buildIssueSummary(slug),
1736
- description: buildIssueDescription({ pluginId, slug, version, manifestJson }),
1737
- tags: ["tracker-plugin"]
1738
- };
1739
- return trackerApiRequest("/issues", {
1740
- method: "POST",
1741
- body
1742
- });
1743
- }
1744
- async function updatePluginIssue(issueKey, params) {
1745
- return trackerApiRequest(`/issues/${issueKey}`, {
1746
- method: "PATCH",
1747
- body: params
1748
- });
1749
- }
1750
- async function attachFileToIssue(issueKey, fileBuffer, fileName) {
1751
- let formData = new import_form_data.default();
1752
- return formData.append("file", fileBuffer, {
1753
- filename: fileName,
1754
- contentType: "application/zip"
1755
- }), trackerApiRequest(`/issues/${issueKey}/attachments`, {
1756
- method: "POST",
1757
- formData
1758
- });
1759
- }
1760
- async function getIssueTransitions(issueKey) {
1761
- return trackerApiRequest(`/issues/${issueKey}/transitions`, {
1762
- method: "GET"
1763
- });
1764
- }
1765
- async function executeIssueTransition(issueKey, transitionId) {
1766
- await trackerApiRequest(`/issues/${issueKey}/transitions/${transitionId}/_execute`, {
1767
- method: "POST",
1768
- body: {}
1769
- });
1770
- }
1771
- async function getIssue(issueKey) {
1772
- return trackerApiRequest(`/issues/${issueKey}`, {
1773
- method: "GET"
1774
- });
1775
- }
1776
- async function getMyPluginIssues() {
1777
- return trackerApiRequest("/issues/_search", {
1778
- method: "POST",
1779
- body: {
1780
- filter: {
1781
- queue: PLUGINMOD_QUEUE,
1782
- createdBy: "me()"
1783
- }
1784
- }
1785
- });
1786
- }
1787
- async function addIssueComment(issueKey, text) {
1788
- await trackerApiRequest(`/issues/${issueKey}/comments`, {
1789
- method: "POST",
1790
- body: { text }
1791
- });
1792
- }
1793
-
1794
- // src/api/utils.ts
1795
- init_logger();
1796
- function mapTrackerStatusToPluginStatus(issue) {
1797
- let statusKey = issue.status.key, resolutionKey = issue.resolution?.key, resolutionDisplay = issue.resolution?.display;
1798
- switch (statusKey) {
1799
- case "open":
1800
- return "draft";
1801
- case "inProgress":
1802
- return "waiting_for_review";
1803
- case "need_info":
1804
- return "need_info";
1805
- case "waitingForApprove":
1806
- return "pending_approval";
1807
- case "closed":
1808
- switch (resolutionKey) {
1809
- case "agreed":
1810
- return "approved";
1811
- case "rejected":
1812
- case "declined":
1813
- return "rejected";
1814
- default:
1815
- return logger_default.warning(
1816
- `[tracker-status-debug] Unknown closed resolution for ${issue.key}: status.key=${statusKey}, status.display=${issue.status.display ?? "n/a"}, resolution.key=${resolutionKey ?? "n/a"}, resolution.display=${resolutionDisplay ?? "n/a"}`
1817
- ), "unknown";
1818
- }
1819
- default:
1820
- return logger_default.warning(
1821
- `[tracker-status-debug] Unknown tracker status for ${issue.key}: status.key=${statusKey}, status.display=${issue.status.display ?? "n/a"}, resolution.key=${resolutionKey ?? "n/a"}, resolution.display=${resolutionDisplay ?? "n/a"}`
1822
- ), "unknown";
1823
- }
1824
- }
1825
-
1826
- // src/core/pluginState/pluginStateManager.ts
1827
- var import_fs10 = require("fs"), import_promises3 = require("fs/promises"), STATE_FILE = ".tracker-plugin", load2 = async () => {
1828
- if (!(0, import_fs10.existsSync)(STATE_FILE))
1829
- return {};
1830
- try {
1831
- let content = await (0, import_promises3.readFile)(STATE_FILE, "utf8");
1832
- return JSON.parse(content);
1833
- } catch {
1834
- return {};
1835
- }
1836
- }, save2 = async (state) => {
1837
- try {
1838
- let content = JSON.stringify(state, null, 4);
1839
- await (0, import_promises3.writeFile)(STATE_FILE, content, "utf8");
1840
- } catch (error2) {
1841
- throw error2 instanceof Error ? new Error(`Error saving ${STATE_FILE}: ${error2.message}`) : new Error(`Error saving ${STATE_FILE}`);
1842
- }
1843
- }, update2 = async (updates) => {
1844
- let updated = { ...await load2(), ...updates };
1845
- return await save2(updated), updated;
1846
- }, pluginStateManager = {
1847
- load: load2,
1848
- save: save2,
1849
- update: update2
1850
- };
1851
-
1852
- // src/commands/info/index.ts
1853
- init_logger();
1854
-
1855
- // src/utils/pluginDisplay.ts
1856
- var import_picocolors3 = __toESM(require("picocolors"));
1857
- init_logger();
1858
- var printHeader = (title) => {
1859
- console.info(import_picocolors3.default.bold(import_picocolors3.default.white(title)));
1860
- }, printSuccessHeader = (title) => {
1861
- console.info(import_picocolors3.default.bold(import_picocolors3.default.green(title)));
1862
- }, getStatusBadge = (status) => {
1863
- let normalized = status.toLowerCase();
1864
- return normalized.includes("approved") ? import_picocolors3.default.black(import_picocolors3.default.bgGreen(` ${status} `)) : normalized.includes("pending") || normalized.includes("review") ? import_picocolors3.default.black(import_picocolors3.default.bgYellow(` ${status} `)) : normalized.includes("rejected") ? import_picocolors3.default.white(import_picocolors3.default.bgRed(` ${status} `)) : normalized.includes("draft") || normalized.includes("unknown") ? import_picocolors3.default.black(import_picocolors3.default.bgWhite(` ${status} `)) : import_picocolors3.default.black(import_picocolors3.default.bgBlue(` ${status} `));
1865
- }, formatDate = (dateString) => dateString ? new Date(dateString).toLocaleString("ru-RU", {
1866
- year: "numeric",
1867
- month: "2-digit",
1868
- day: "2-digit",
1869
- hour: "2-digit",
1870
- minute: "2-digit"
1871
- }) : "-", printField = (label, value, minWidth = 12) => {
1872
- console.info(` ${import_picocolors3.default.dim(label.padEnd(minWidth))} ${value}`);
1873
- }, printPluginId = (pluginId) => {
1874
- printField("Plugin ID", import_picocolors3.default.cyan(pluginId));
1875
- };
1876
- var printStatus = (status) => {
1877
- printField("Status", getStatusBadge(status.toUpperCase()));
1878
- }, printCreated = (createdAt) => {
1879
- printField("Created", import_picocolors3.default.white(formatDate(createdAt)));
1880
- }, printUpdated = (updatedAt) => {
1881
- printField("Updated", import_picocolors3.default.white(formatDate(updatedAt)));
1882
- };
1883
- function showPluginInfo(data) {
1884
- printHeader("\u{1F4E6} Plugin"), logger_default.newLine(), printPluginId(data.id), printField("Slug", import_picocolors3.default.magenta(data.slug)), printField("Name", import_picocolors3.default.white(data.name)), printStatus(data.status), data.createdAt && printCreated(data.createdAt), data.updatedAt && printUpdated(data.updatedAt);
1885
- }
1886
- function showPluginVersions(versions2) {
1887
- if (!versions2 || versions2.length === 0) {
1888
- console.info(import_picocolors3.default.dim(" No versions found")), logger_default.newLine();
1889
- return;
1890
- }
1891
- printHeader(`\u{1F9FE} Versions \xB7 ${versions2.length}`), logger_default.newLine(), versions2.forEach((version, index) => {
1892
- console.info(` ${import_picocolors3.default.bold(String(index + 1) + ".")} ${import_picocolors3.default.cyan(version.versionId)}`), printField("Status", getStatusBadge(version.status.toUpperCase())), printField("Version", import_picocolors3.default.white(version.version)), printCreated(version.createdAt), logger_default.newLine();
1893
- });
1894
- }
1895
- function showPluginCreated(data) {
1896
- printSuccessHeader("\u2705 Plugin Created"), logger_default.newLine(), printPluginId(data.id);
1897
- }
1898
- function showTrackerPluginList(issues, mapStatus) {
1899
- if (!issues || issues.length === 0) {
1900
- console.info(import_picocolors3.default.dim(" No plugins found")), logger_default.newLine();
1901
- return;
1902
- }
1903
- printHeader(`\u{1F4CB} Your Plugins \xB7 ${issues.length}`), logger_default.newLine(), issues.forEach((issue) => {
1904
- let slugMatch = issue.summary.match(/^Plugin:\s*(.+)$/), slug = slugMatch ? import_picocolors3.default.magenta(slugMatch[1].trim()) : import_picocolors3.default.dim(issue.summary), lifecycleStatus = mapStatus(issue), statusBadge = getStatusBadge(lifecycleStatus.toUpperCase());
1905
- console.info(
1906
- ` ${slug} ${import_picocolors3.default.dim("\xB7")} ${statusBadge} ${import_picocolors3.default.dim("\xB7")} ${import_picocolors3.default.dim(issue.key)}`
1907
- ), logger_default.newLine();
1908
- });
1909
- }
1910
- function showTrackerPluginInfo(issue, mapStatus) {
1911
- printHeader("\u{1F4E6} Plugin"), logger_default.newLine(), printField("Issue key", import_picocolors3.default.cyan(issue.key)), printField("Status", getStatusBadge(mapStatus(issue).toUpperCase())), printField("Summary", import_picocolors3.default.white(issue.summary)), issue.createdAt && printCreated(issue.createdAt), issue.updatedAt && printUpdated(issue.updatedAt);
1912
- }
1913
-
1914
- // src/commands/info/index.ts
1915
- async function info2(issueKey) {
1916
- let targetIssueKey = issueKey;
1917
- if (targetIssueKey || (targetIssueKey = (await pluginStateManager.load()).trackerIssueKey), !targetIssueKey) {
1918
- logger_default.warning(
1919
- 'No issue key provided and plugin is not registered. Run "tracker-cli register" first.'
1920
- ), logger_default.suggest("tracker-cli register");
1921
- return;
1922
- }
1923
- logger_default.info(`\u23F3 Fetching plugin info for ${targetIssueKey}...`);
1924
- try {
1925
- let issue = await getIssue(targetIssueKey);
1926
- showTrackerPluginInfo(issue, mapTrackerStatusToPluginStatus);
1927
- } catch (error2) {
1928
- throw logger_default.error(`Failed to fetch plugin info for ${targetIssueKey}`), error2;
1929
- }
1930
- }
1931
-
1932
- // src/commands/install/index.ts
1933
- init_logger();
1934
-
1935
- // src/commands/install/utils/mergeConfigs.ts
1936
- var mergeConfigs = (config, newConfig) => {
1937
- let result = { ...config };
1938
- for (let [key, newItems] of Object.entries(newConfig)) {
1939
- let slotKey = key;
1940
- if (!newItems || !Array.isArray(newItems))
1941
- continue;
1942
- let existingItems = result[slotKey];
1943
- if (!existingItems) {
1944
- result[slotKey] = [...newItems];
1945
- continue;
1946
- }
1947
- let mergedItems = [];
1948
- for (let existingItem of existingItems)
1949
- newItems.some(
1950
- (newItem) => newItem.slug === existingItem.slug
1951
- ) || mergedItems.push(existingItem);
1952
- mergedItems.push(...newItems), result[slotKey] = mergedItems;
1953
- }
1954
- return result;
1955
- };
1956
-
1957
- // src/commands/install/index.ts
1958
- async function install() {
1959
- await s3Manager.checkMdsAuth();
1960
- let environment = await promptEnvironment();
1961
- s3Manager.setEnvironment(environment);
1962
- let [config, manifest] = await Promise.all([
1963
- s3Manager.getPluginsConfig(),
1964
- manifestManager.load()
1965
- ]), pluginConfig = convertManifestToConfig(manifest, environment), mergedConfig = mergeConfigs(config, pluginConfig);
1966
- await s3Manager.savePluginsConfig(mergedConfig), logger_default.info("\u{1F389} Installation completed successfully!");
1967
- }
1968
-
1969
1373
  // src/commands/lint.ts
1970
1374
  init_logger();
1971
1375
  async function lint() {
1972
1376
  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);
1973
1377
  }
1974
1378
 
1975
- // src/commands/list/index.ts
1976
- init_logger();
1977
- async function list() {
1978
- logger_default.info("\u23F3 Fetching my plugins from Tracker...");
1979
- try {
1980
- let issues = await getMyPluginIssues();
1981
- showTrackerPluginList(issues, mapTrackerStatusToPluginStatus);
1982
- } catch (error2) {
1983
- throw logger_default.error("Failed to fetch plugins list"), error2;
1984
- }
1985
- }
1986
-
1987
- // src/api/apiRequest.ts
1988
- async function apiRequest(endpoint, options = {}) {
1989
- let { method = "GET", body, headers = {}, token } = options, authHeader = token ? `OAuth ${token}` : authManager.authHeader;
1990
- if (!authHeader)
1991
- throw new Error('Not authenticated. Run "tracker-cli login" first.');
1992
- let requestHeaders = {
1993
- Authorization: authHeader,
1994
- "Content-Type": "application/json",
1995
- ...headers
1996
- }, requestOptions = {
1997
- method,
1998
- headers: requestHeaders
1999
- };
2000
- body && method !== "GET" && (requestOptions.body = JSON.stringify(body));
2001
- let url = `${getTrackerBaseUrl2()}${endpoint}`, response = await fetch(url, requestOptions);
2002
- if (!response.ok)
2003
- throw new Error([response.status, response.statusText].join(" ").trim());
2004
- let contentType = response.headers.get("content-type");
2005
- return contentType && contentType.includes("application/json") ? await response.json() : await response.text();
2006
- }
2007
-
2008
- // src/api/user.ts
2009
- async function getMyself() {
2010
- return await apiRequest("/myself");
2011
- }
2012
- async function verifyToken(token) {
2013
- return await apiRequest("/myself", { token });
2014
- }
2015
-
2016
- // src/commands/login/index.ts
2017
- init_logger();
2018
-
2019
- // src/commands/login/utils/promptForCredentials.ts
2020
- var import_prompts5 = require("@inquirer/prompts"), import_picocolors4 = __toESM(require("picocolors"));
2021
- var ESC = "\x1B", BEL = "\x07", promptForCredentials = async () => {
2022
- let tokenUrl = getOAuthTokenUrl2();
2023
- return console.info(
2024
- import_picocolors4.default.dim("Get your OAuth token at: ") + import_picocolors4.default.cyan(`${ESC}]8;;${tokenUrl}${BEL}${tokenUrl}${ESC}]8;;${BEL}`)
2025
- ), console.info(""), {
2026
- token: (await (0, import_prompts5.input)({
2027
- message: "Enter your Yandex Tracker OAuth token:",
2028
- required: !0
2029
- })).trim()
2030
- };
2031
- };
2032
-
2033
- // src/commands/login/index.ts
2034
- async function login() {
2035
- let authToken = (await promptForCredentials()).token;
2036
- try {
2037
- let userInfo = await verifyToken(authToken);
2038
- authManager.saveAuthData(authToken), logger_default.success(`Successfully logged in as ${userInfo.login}`);
2039
- } catch (error2) {
2040
- logger_default.error("Invalid token or API request failed", error2);
2041
- }
2042
- }
2043
-
2044
- // src/commands/logout.ts
2045
- init_logger();
2046
- function logout() {
2047
- try {
2048
- if (!authManager.data) {
2049
- logger_default.warning("You are not logged in");
2050
- return;
2051
- }
2052
- authManager.removeAuthData(), logger_default.success("Successfully logged out");
2053
- } catch (error2) {
2054
- logger_default.error("Logout failed", error2);
2055
- }
2056
- }
2057
-
2058
- // src/commands/register/index.ts
2059
- init_logger();
2060
-
2061
- // src/commands/submit/index.ts
2062
- init_logger();
2063
-
2064
- // src/commands/uninstall/index.ts
2065
- init_logger();
2066
-
2067
- // src/commands/uninstall/utils/removePluginFromConfig.ts
2068
- var removePluginFromConfig = (config, pluginSlug) => {
2069
- let removedFromSlots = [], updatedConfig = {};
2070
- return Object.keys(config).forEach((slotName) => {
2071
- let slotPlugins = config[slotName];
2072
- if (!slotPlugins)
2073
- return;
2074
- let filteredPlugins = slotPlugins.filter((plugin) => plugin.slug !== pluginSlug);
2075
- filteredPlugins.length < slotPlugins.length && removedFromSlots.push(slotName), updatedConfig[slotName] = filteredPlugins;
2076
- }), { updatedConfig, removedFromSlots };
2077
- };
2078
-
2079
- // src/commands/uninstall/index.ts
2080
- async function uninstall() {
2081
- await s3Manager.checkMdsAuth();
2082
- let [config, manifest] = await Promise.all([
2083
- s3Manager.getPluginsConfig(),
2084
- manifestManager.load()
2085
- ]);
2086
- if (Object.keys(config).length === 0) {
2087
- logger_default.info("\u{1F50D} Config is empty. Nothing to uninstall.");
2088
- return;
2089
- }
2090
- let { updatedConfig, removedFromSlots } = removePluginFromConfig(config, manifest.slug);
2091
- if (removedFromSlots.length === 0) {
2092
- logger_default.info(
2093
- `\u{1F50D} Plugin ${manifest.slug} not found in config. It may have already been removed.`
2094
- );
2095
- return;
2096
- }
2097
- await s3Manager.savePluginsConfig(updatedConfig), logger_default.success(
2098
- `Plugin ${manifest.slug} successfully removed from slots: ${removedFromSlots.join(", ")}`
2099
- );
2100
- }
2101
-
2102
1379
  // src/commands/up/utils/copyTemplateFiles.ts
2103
- var import_fs11 = require("fs"), import_promises4 = require("fs/promises");
1380
+ var import_fs7 = require("fs"), import_promises2 = require("fs/promises");
2104
1381
  var copyTemplateFiles = async (filenames) => {
2105
1382
  await Promise.all(
2106
1383
  filenames.map(async (filename) => {
2107
1384
  let templatePath = getTemplatePath(filename), targetPath = `./${filename}`;
2108
- (0, import_fs11.existsSync)(templatePath) && (0, import_fs11.existsSync)(targetPath) && await (0, import_promises4.copyFile)(templatePath, targetPath);
1385
+ if ((0, import_fs7.existsSync)(templatePath) && (0, import_fs7.existsSync)(targetPath)) {
1386
+ let content = await (0, import_promises2.readFile)(templatePath), rewritten = applySubstitutions2(filename, content);
1387
+ await (0, import_promises2.writeFile)(targetPath, rewritten);
1388
+ }
2109
1389
  })
2110
1390
  );
2111
1391
  };
@@ -2117,481 +1397,42 @@ async function updateManifestCompatibility() {
2117
1397
  }
2118
1398
 
2119
1399
  // src/commands/up/utils/updatePackageDependencies.ts
2120
- var import_fs12 = require("fs"), import_promises5 = require("fs/promises");
1400
+ var import_fs8 = require("fs"), import_promises3 = require("fs/promises");
2121
1401
  var updatePackageDependencies = async (dependencies) => {
2122
1402
  let packageJsonPath = "./package.json", templatePackageJsonPath = getTemplatePath("package.json");
2123
- if (!(0, import_fs12.existsSync)(packageJsonPath) || !(0, import_fs12.existsSync)(templatePackageJsonPath))
1403
+ if (!(0, import_fs8.existsSync)(packageJsonPath) || !(0, import_fs8.existsSync)(templatePackageJsonPath))
2124
1404
  return;
2125
- let packageJsonContent = await (0, import_promises5.readFile)(packageJsonPath, "utf-8"), templatePackageJsonContent = await (0, import_promises5.readFile)(templatePackageJsonPath, "utf-8"), packageJson = JSON.parse(packageJsonContent), templatePackageJson = JSON.parse(templatePackageJsonContent), updated = !1;
1405
+ let packageJsonContent = await (0, import_promises3.readFile)(packageJsonPath, "utf-8"), templatePackageJsonRaw = await (0, import_promises3.readFile)(templatePackageJsonPath), templatePackageJsonContent = applySubstitutions2(
1406
+ "package.json",
1407
+ templatePackageJsonRaw
1408
+ ).toString("utf8"), packageJson = JSON.parse(packageJsonContent), templatePackageJson = JSON.parse(templatePackageJsonContent), updated = !1;
2126
1409
  dependencies.forEach((dep) => {
2127
1410
  packageJson.dependencies?.[dep] && templatePackageJson.dependencies?.[dep] && packageJson.dependencies[dep] !== templatePackageJson.dependencies[dep] && (packageJson.dependencies[dep] = templatePackageJson.dependencies[dep], updated = !0);
2128
- }), updated && await (0, import_promises5.writeFile)(packageJsonPath, JSON.stringify(packageJson, null, 4) + `
1411
+ }), updated && await (0, import_promises3.writeFile)(packageJsonPath, JSON.stringify(packageJson, null, 4) + `
2129
1412
  `, "utf-8");
2130
1413
  };
2131
1414
 
2132
1415
  // src/commands/up/index.ts
2133
- var templateFiles = ["manifest.schema.json", "vite.config.ts"], templateDeps = [
2134
- "@yandex-data-ui/tracker-plugin-sdk-react",
2135
- "@yandex-data-ui/tracker-pub-api-types"
2136
- ];
1416
+ var templateFiles = ["manifest.schema.json", "vite.config.ts"];
2137
1417
  async function up() {
2138
- await copyTemplateFiles(templateFiles), await updateManifestCompatibility(), await updatePackageDependencies(templateDeps);
2139
- }
2140
-
2141
- // src/utils/buildArchive.ts
2142
- var import_path12 = __toESM(require("path")), import_archiver = __toESM(require("archiver"));
2143
- init_logger();
2144
-
2145
- // src/utils/marketplace.ts
2146
- var import_fs13 = __toESM(require("fs")), import_path11 = __toESM(require("path"));
2147
- init_logger();
2148
- var 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) => {
2149
- import_fs13.default.existsSync(targetPath) || (logger_default.error(errorMessage), process.exit(1));
2150
- }, ensureManifestCatalogFields = (manifest) => {
2151
- (!manifest.name?.ru || !manifest.name?.en) && (logger_default.error(
2152
- 'Manifest field "name" is required for publishing. Add localized "name.ru" and "name.en" to ./manifest.json.'
2153
- ), process.exit(1)), (!manifest.description?.ru || !manifest.description?.en) && (logger_default.error(
2154
- 'Manifest field "description" is required for publishing. Add localized "description.ru" and "description.en" to ./manifest.json.'
2155
- ), process.exit(1));
2156
- };
2157
- function validateMarketplaceAssets() {
2158
- let marketplaceDir = import_path11.default.resolve(MARKETPLACE_DIR);
2159
- ensurePathExists(
2160
- marketplaceDir,
2161
- "Marketplace folder not found. Create ./marketplace and add index.md and header-image.jpg before publishing."
2162
- ), ensurePathExists(
2163
- import_path11.default.join(marketplaceDir, MARKETPLACE_INDEX_FILE),
2164
- "Marketplace description not found. Add ./marketplace/index.md before publishing."
2165
- ), ensurePathExists(
2166
- import_path11.default.join(marketplaceDir, MARKETPLACE_HEADER_IMAGE_FILE),
2167
- "Marketplace header image not found. Add ./marketplace/header-image.jpg before publishing."
2168
- ), ensurePathExists(
2169
- import_path11.default.resolve(PUBLIC_DIR, PUBLIC_LOGO_FILE),
2170
- "Plugin logo not found. Add ./public/logo.svg before publishing."
2171
- );
2172
- }
2173
- function validateArchiveSources() {
2174
- ensurePathExists(import_path11.default.resolve(DIST_DIR), "Dist folder not found. Build the project first."), ensurePathExists(
2175
- import_path11.default.resolve(SRC_DIR),
2176
- "Source folder not found. Add ./src before publishing."
2177
- ), ensurePathExists(import_path11.default.resolve(MANIFEST_FILE), "manifest.json not found in plugin root."), validateMarketplaceAssets();
2178
- }
2179
- async function getMarketplaceCatalogEntry() {
2180
- let indexPath = import_path11.default.resolve(MARKETPLACE_DIR, MARKETPLACE_INDEX_FILE);
2181
- ensurePathExists(
2182
- indexPath,
2183
- "Marketplace description not found. Add ./marketplace/index.md before uploading."
2184
- );
2185
- let manifest = await manifestManager.load();
2186
- ensureManifestCatalogFields(manifest);
2187
- let longDescription = import_fs13.default.readFileSync(indexPath, "utf-8").trim();
2188
- return {
2189
- name: manifest.name.ru,
2190
- description: manifest.description.ru,
2191
- longDescription,
2192
- tags: manifest.keywords ?? []
2193
- };
2194
- }
2195
- function getMarketplaceHeaderImage() {
2196
- let imagePath = import_path11.default.resolve(MARKETPLACE_DIR, MARKETPLACE_HEADER_IMAGE_FILE);
2197
- return ensurePathExists(
2198
- imagePath,
2199
- "Marketplace header image not found. Add ./marketplace/header-image.jpg before uploading."
2200
- ), {
2201
- buffer: import_fs13.default.readFileSync(imagePath),
2202
- filename: MARKETPLACE_HEADER_IMAGE_FILE
2203
- };
2204
- }
2205
- var marketplacePaths = {
2206
- distDir: DIST_DIR,
2207
- srcDir: SRC_DIR,
2208
- marketplaceDir: MARKETPLACE_DIR,
2209
- manifestFile: MANIFEST_FILE
2210
- };
2211
-
2212
- // src/utils/buildArchive.ts
2213
- init_verbose();
2214
- async function buildArchive() {
2215
- return validateArchiveSources(), (await manifestManager.load()).manifest_version === void 0 && (logger_default.error(
2216
- 'manifest_version is missing in manifest.json. Run "tracker-cli up" or add "manifest_version": 1 manually before uploading.'
2217
- ), process.exit(1)), new Promise((resolve2, reject) => {
2218
- let archive = (0, import_archiver.default)("zip", { zlib: { level: 9 } }), chunks = [];
2219
- archive.on("data", (chunk) => chunks.push(chunk)), archive.on("end", () => {
2220
- let buffer = Buffer.concat(chunks);
2221
- if (logger_default.info(`\u{1F4E6} Archive created (${buffer.length} bytes)`), isVerboseEnabled()) {
2222
- let debugPath = writeVerboseArtifact("archive/latest-upload.zip", buffer);
2223
- logger_default.info(`[platform-api-debug] Saved archive copy to ${debugPath}`);
2224
- }
2225
- resolve2(buffer);
2226
- }), archive.on("error", reject), archive.file(import_path12.default.resolve(marketplacePaths.manifestFile), { name: "manifest.json" }), archive.glob(
2227
- "**/*",
2228
- {
2229
- cwd: import_path12.default.resolve(marketplacePaths.distDir),
2230
- ignore: ["**/.DS_Store"]
2231
- },
2232
- { prefix: "dist/" }
2233
- ), archive.glob(
2234
- "**/*",
2235
- {
2236
- cwd: import_path12.default.resolve(marketplacePaths.srcDir),
2237
- ignore: ["**/.DS_Store"]
2238
- },
2239
- { prefix: "src/" }
2240
- ), archive.finalize();
2241
- });
2242
- }
2243
-
2244
- // src/commands/upload/index.ts
2245
- init_logger();
2246
-
2247
- // src/api/platform.ts
2248
- var import_form_data2 = __toESM(require("form-data"));
2249
-
2250
- // src/api/platformApiRequest.ts
2251
- var import_node_fetch3 = __toESM(require("node-fetch"));
2252
- init_logger();
2253
- init_verbose();
2254
- var PLATFORM_API_TIMEOUT_MS = Number(process.env.TRACKER_CLI_PLATFORM_TIMEOUT_MS || 3e4);
2255
- function buildRequestHeaders(headers, formData) {
2256
- let authHeader = authManager.authHeader;
2257
- if (!authHeader)
2258
- throw new Error('Not authenticated. Run "tracker-cli login" first.');
2259
- let requestHeaders = {
2260
- Accept: "*/*",
2261
- Authorization: authHeader,
2262
- ...headers
2263
- };
2264
- return formData || (requestHeaders["Content-Type"] = "application/json"), requestHeaders;
2265
- }
2266
- function buildRequestBody(method, body, formData) {
2267
- if (formData) {
2268
- let formHeaders = formData.getHeaders?.();
2269
- return {
2270
- body: formData,
2271
- headers: formHeaders || {}
2272
- };
2273
- }
2274
- return body && method !== "GET" ? { body: JSON.stringify(body) } : {};
2275
- }
2276
- function buildQueryString2(queryParams) {
2277
- if (!queryParams || Object.keys(queryParams).length === 0)
2278
- return "";
2279
- let params = new URLSearchParams();
2280
- return Object.entries(queryParams).forEach(([key, value]) => {
2281
- params.append(key, String(value));
2282
- }), `?${params.toString()}`;
2283
- }
2284
- async function parseResponse2(response) {
2285
- 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();
2286
- }
2287
- async function platformApiRequest(endpoint, options = {}) {
2288
- let { method = "GET", body, headers = {}, formData, queryParams } = options, requestHeaders = buildRequestHeaders(headers, formData), { body: requestBody, headers: additionalHeaders } = buildRequestBody(
2289
- method,
2290
- body,
2291
- formData
2292
- ), requestOptions = {
2293
- method,
2294
- headers: { ...requestHeaders, ...additionalHeaders },
2295
- body: requestBody
2296
- }, queryString = buildQueryString2(queryParams), url = `${getPlatformBaseUrl2()}${endpoint}${queryString}`, controller = new AbortController(), timeout = setTimeout(() => controller.abort(), PLATFORM_API_TIMEOUT_MS);
2297
- if (isVerboseEnabled() && (logger_default.info(
2298
- `[platform-api-debug] Request: method=${method} url=${url} hasBody=${!!body} hasFormData=${!!formData} timeoutMs=${PLATFORM_API_TIMEOUT_MS}`
2299
- ), body !== void 0 && logger_default.info(`[platform-api-debug] Request body: ${JSON.stringify(body)}`), formData)) {
2300
- let debugPath = writeVerboseArtifact(
2301
- "requests/latest-form-data.txt",
2302
- `method=${method}
2303
- url=${url}
2304
- headers=${JSON.stringify({ ...requestHeaders, ...additionalHeaders }, null, 2)}
2305
- formData=present
2306
- `
2307
- );
2308
- logger_default.info(`[platform-api-debug] Saved form-data request metadata to ${debugPath}`);
2309
- }
2310
- try {
2311
- let response = await (0, import_node_fetch3.default)(url, {
2312
- ...requestOptions,
2313
- signal: controller.signal
2314
- });
2315
- if (isVerboseEnabled() && logger_default.info(
2316
- `[platform-api-debug] Response: method=${method} url=${url} status=${response.status} contentType=${response.headers.get("content-type") ?? "n/a"}`
2317
- ), !response.ok) {
2318
- let errorText = await response.text(), errorMessage = errorText;
2319
- try {
2320
- let errorJson = JSON.parse(errorText);
2321
- errorJson.message && (errorMessage = errorJson.message);
2322
- } catch {
2323
- }
2324
- throw new Error(errorMessage);
2325
- }
2326
- return parseResponse2(response);
2327
- } catch (error2) {
2328
- throw error2 instanceof Error && error2.name === "AbortError" ? new Error(
2329
- `Platform API request timed out after ${PLATFORM_API_TIMEOUT_MS}ms: ${method} ${url}`
2330
- ) : error2;
2331
- } finally {
2332
- clearTimeout(timeout);
2333
- }
2334
- }
2335
-
2336
- // src/api/platform.ts
2337
- async function createPlugin(archiveBuffer, archiveName) {
2338
- let formData = new import_form_data2.default();
2339
- return formData.append("archive", archiveBuffer, {
2340
- filename: archiveName,
2341
- contentType: "application/zip"
2342
- }), platformApiRequest("/api/v1/plugins", {
2343
- method: "POST",
2344
- formData
2345
- });
2346
- }
2347
- async function updatePluginArchive(pluginId, archiveBuffer, archiveName) {
2348
- let formData = new import_form_data2.default();
2349
- return formData.append("archive", archiveBuffer, {
2350
- filename: archiveName,
2351
- contentType: "application/zip"
2352
- }), platformApiRequest(`/api/v1/plugins/${pluginId}/archive`, {
2353
- method: "PUT",
2354
- formData
2355
- });
2356
- }
2357
- async function updateCatalogEntry(pluginId, catalogData) {
2358
- return platformApiRequest(`/api/v1/plugins/${pluginId}/catalog-entry`, {
2359
- method: "PUT",
2360
- body: catalogData
2361
- });
2362
- }
2363
- async function updateCatalogImage(pluginId, imageBuffer, imageName) {
2364
- let formData = new import_form_data2.default();
2365
- return formData.append("image", imageBuffer, {
2366
- filename: imageName,
2367
- contentType: "image/jpeg"
2368
- }), platformApiRequest(`/api/v1/plugins/${pluginId}/catalog-image`, {
2369
- method: "PUT",
2370
- formData
2371
- });
2372
- }
2373
- async function submitPlugin(pluginId, version) {
2374
- return platformApiRequest(`/api/v1/plugins/${pluginId}/submit`, {
2375
- method: "POST",
2376
- queryParams: {
2377
- version
2378
- }
2379
- });
2380
- }
2381
- async function getPluginInfo(pluginId) {
2382
- return platformApiRequest(`/api/v1/plugins/${pluginId}`, {
2383
- method: "GET"
2384
- });
2385
- }
2386
- async function getPluginVersions(pluginId) {
2387
- return platformApiRequest(`/api/v1/plugins/${pluginId}/versions`, {
2388
- method: "GET"
2389
- });
2390
- }
2391
- async function checkSlugAvailability(slug) {
2392
- return platformApiRequest(`/api/v1/slugs/${slug}/available`, {
2393
- method: "GET"
2394
- });
2395
- }
2396
-
2397
- // src/utils/getPluginId.ts
2398
- async function getPluginId(pluginId) {
2399
- if (pluginId)
2400
- return pluginId;
2401
- try {
2402
- let manifest = await manifestManager.load();
2403
- if (!manifest.id)
2404
- throw new Error("Plugin ID not found in manifest.json");
2405
- return manifest.id;
2406
- } catch {
2407
- throw new Error("Plugin ID must be provided as argument or present in manifest.json");
2408
- }
2409
- }
2410
-
2411
- // src/commands/versions/index.ts
2412
- init_logger();
2413
- async function versions(pluginId) {
2414
- let actualPluginId = await getPluginId(pluginId);
2415
- logger_default.info(`\u23F3 Fetching versions for plugin ID: ${actualPluginId}...`);
2416
- try {
2417
- let pluginVersions = await getPluginVersions(actualPluginId);
2418
- if (!pluginVersions || pluginVersions.length === 0) {
2419
- logger_default.info("No versions found for this plugin.");
2420
- return;
2421
- }
2422
- showPluginVersions(pluginVersions), logger_default.newLine();
2423
- } catch (error2) {
2424
- throw logger_default.error(`Failed to fetch versions for plugin ID: ${actualPluginId}`), error2;
2425
- }
2426
- }
2427
-
2428
- // src/commands/whoami.ts
2429
- init_logger();
2430
- async function whoami() {
2431
- if (!authManager.data) {
2432
- logger_default.warning("You are not logged in"), logger_default.suggest("tracker-cli login");
2433
- return;
2434
- }
2435
- try {
2436
- let userInfo = await getMyself();
2437
- logger_default.info(`Current user: ${userInfo.login}`);
2438
- } catch {
2439
- logger_default.warning("Failed to verify token with API");
2440
- }
2441
- }
2442
-
2443
- // src/commands/info/platform.ts
2444
- init_logger();
2445
- async function infoPlatform(pluginId) {
2446
- let actualPluginId = await getPluginId(pluginId);
2447
- logger_default.info(`\u23F3 Fetching plugin info for ID: ${actualPluginId}...`);
2448
- try {
2449
- let pluginInfo = await getPluginInfo(actualPluginId);
2450
- showPluginInfo(pluginInfo), pluginInfo.versions && pluginInfo.versions.length > 0 && (logger_default.newLine(), showPluginVersions(pluginInfo.versions));
2451
- } catch (error2) {
2452
- throw logger_default.error(`Failed to fetch plugin info for ID: ${actualPluginId}`), error2;
2453
- }
2454
- }
2455
-
2456
- // src/commands/submit/platform.ts
2457
- init_logger();
2458
-
2459
- // src/commands/submit/utils/validateSlug.ts
2460
- var readline = __toESM(require("readline"));
2461
- init_logger();
2462
- function promptForSlug() {
2463
- return new Promise((resolve2) => {
2464
- let rl = readline.createInterface({
2465
- input: process.stdin,
2466
- output: process.stdout
2467
- });
2468
- rl.question("Enter a new slug: ", (answer) => {
2469
- rl.close(), resolve2(answer.trim());
2470
- });
2471
- });
2472
- }
2473
- async function validateAndGetUniqueSlug(currentSlug) {
2474
- let slugToCheck = currentSlug, isValid = !1;
2475
- for (; !isValid; )
2476
- try {
2477
- if ((await checkSlugAvailability(slugToCheck)).available)
2478
- return isValid = !0, slugToCheck;
2479
- logger_default.error(`\u274C Slug "${slugToCheck}" is already taken.`), logger_default.info("Please enter a different slug."), slugToCheck = await promptForSlug(), slugToCheck || (logger_default.error("Slug cannot be empty. Please try again."), slugToCheck = currentSlug);
2480
- } catch (error2) {
2481
- throw logger_default.error(`Failed to check slug availability: ${error2.message}`), error2;
2482
- }
2483
- return slugToCheck;
2484
- }
2485
-
2486
- // src/commands/submit/platform.ts
2487
- var SUBMIT_TRANSITION_DISPLAY = "waiting for approve";
2488
- async function submitPlatform() {
2489
- let manifest = await manifestManager.load(), state = await pluginStateManager.load();
2490
- validateMarketplaceAssets(), await build(), logger_default.info("\u{1F4E6} Creating archive...");
2491
- let archiveBuffer = await buildArchive(), archiveName = `${manifest.slug}-${manifest.version}.zip`, pluginId = manifest.id;
2492
- if (pluginId)
2493
- logger_default.info("\u{1F4E4} Updating plugin archive..."), await updatePluginArchive(pluginId, archiveBuffer, archiveName);
2494
- else {
2495
- logger_default.info("\u23F3 Creating plugin...");
2496
- let createdPlugin = await createPlugin(archiveBuffer, archiveName);
2497
- showPluginCreated(createdPlugin), pluginId = createdPlugin.id, await manifestManager.update({ id: pluginId });
2498
- }
2499
- let manifestContent = await manifestManager.loadRaw(), issueKey = state.trackerIssueKey;
2500
- if (!issueKey) {
2501
- logger_default.info("\u23F3 Creating plugin issue in Tracker...");
2502
- let issue = await createPluginIssue({
2503
- pluginId,
2504
- slug: manifest.slug,
2505
- version: manifest.version,
2506
- manifestJson: manifestContent
2507
- });
2508
- await pluginStateManager.update({ trackerIssueKey: issue.key }), issueKey = issue.key;
2509
- }
2510
- let catalogEntry = await getMarketplaceCatalogEntry();
2511
- logger_default.info("\u{1F4DD} Updating catalog entry from ./marketplace/index.md..."), await updateCatalogEntry(pluginId, catalogEntry);
2512
- let headerImage = getMarketplaceHeaderImage();
2513
- logger_default.info("\u{1F5BC}\uFE0F Uploading catalog image from ./marketplace/header-image.jpg..."), await updateCatalogImage(pluginId, headerImage.buffer, headerImage.filename);
2514
- let validatedSlug = await validateAndGetUniqueSlug(manifest.slug);
2515
- validatedSlug !== manifest.slug && await manifestManager.update({ slug: validatedSlug }), await submitPlugin(pluginId, manifest.version);
2516
- let transitions = await getIssueTransitions(issueKey), submitTransition = transitions.find(
2517
- (t) => t.display?.toLowerCase().includes(SUBMIT_TRANSITION_DISPLAY) || t.id?.toLowerCase().includes("waitingforapprove") || t.id?.toLowerCase().includes("waiting")
2518
- );
2519
- if (!submitTransition) {
2520
- let available = transitions.map((t) => `"${t.display ?? t.id}"`).join(", ");
2521
- logger_default.error(
2522
- `Could not find a "Waiting for approve" transition on ${issueKey}. Available: ${available}`
2523
- );
2524
- return;
2525
- }
2526
- logger_default.info("\u{1F680} Submitting 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();
2527
- }
2528
-
2529
- // src/commands/submit/tracker.ts
2530
- var import_crypto = require("crypto");
2531
- init_logger();
2532
- var SUBMIT_TRANSITION_DISPLAY2 = "waiting for approve";
2533
- async function submitTracker() {
2534
- let manifest = await manifestManager.load(), issueKey = (await pluginStateManager.load()).trackerIssueKey;
2535
- if (issueKey)
2536
- try {
2537
- await getIssue(issueKey);
2538
- } catch {
2539
- issueKey = void 0;
2540
- }
2541
- let pluginId = manifest.id ?? (0, import_crypto.randomUUID)();
2542
- manifest.id || await manifestManager.update({ id: pluginId });
2543
- let manifestJson = await manifestManager.loadRaw();
2544
- if (issueKey) {
2545
- logger_default.verbose(`\u23F3 Updating issue ${issueKey} with latest manifest...`);
2546
- let issueDescription = buildIssueDescription({
2547
- pluginId,
2548
- slug: manifest.slug,
2549
- version: manifest.version,
2550
- manifestJson
2551
- });
2552
- await updatePluginIssue(issueKey, { description: issueDescription });
2553
- } else {
2554
- logger_default.info("\u23F3 Creating plugin issue in Tracker...");
2555
- let issue = await createPluginIssue({
2556
- pluginId,
2557
- slug: manifest.slug,
2558
- version: manifest.version,
2559
- manifestJson
2560
- });
2561
- await pluginStateManager.update({ trackerIssueKey: issue.key }), issueKey = issue.key, logger_default.info(` Tracker issue : ${issueKey}`);
2562
- }
2563
- logger_default.info("\u{1F528} Building plugin..."), await build(), logger_default.info("\u{1F4E6} Creating archive...");
2564
- let archiveBuffer = await buildArchive(), archiveName = `${manifest.slug}-${manifest.version}.zip`;
2565
- logger_default.verbose(`\u2B06\uFE0F Attaching ${archiveName} to ${issueKey}...`), await attachFileToIssue(issueKey, archiveBuffer, archiveName), await addIssueComment(
2566
- issueKey,
2567
- `Updated bundle: \`${archiveName}\` (${archiveBuffer.length} bytes)`
2568
- ), logger_default.verbose(`\u23F3 Fetching available transitions for ${issueKey}...`);
2569
- let transitions = await getIssueTransitions(issueKey), submitTransition = transitions.find(
2570
- (t) => t.display?.toLowerCase().includes(SUBMIT_TRANSITION_DISPLAY2) || t.id?.toLowerCase().includes("waitingforapprove") || t.id?.toLowerCase().includes("waiting")
2571
- );
2572
- if (!submitTransition) {
2573
- let available = transitions.map((t) => `"${t.display ?? t.id}"`).join(", ");
2574
- logger_default.error(
2575
- `Could not find a "Waiting for approve" transition on ${issueKey}. Available: ${available}`
2576
- );
2577
- return;
2578
- }
2579
- 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();
1418
+ await copyTemplateFiles(templateFiles), await updateManifestCompatibility(), await updatePackageDependencies(templateDeps2);
2580
1419
  }
2581
1420
 
2582
1421
  // src/utils/getVersion.ts
2583
- var import_fs14 = require("fs"), import_path13 = require("path"), UNKNOWN_VERSION = "unknown", getVersionFromPackageJson = () => {
1422
+ var import_fs9 = require("fs"), import_path9 = require("path"), UNKNOWN_VERSION = "unknown", getVersionFromPackageJson = () => {
2584
1423
  try {
2585
- let packagePath = (0, import_path13.resolve)(__dirname, "../../package.json");
2586
- return (0, import_fs14.existsSync)(packagePath) && JSON.parse((0, import_fs14.readFileSync)(packagePath, "utf-8")).version || null;
1424
+ let packagePath = (0, import_path9.resolve)(__dirname, "../../package.json");
1425
+ return (0, import_fs9.existsSync)(packagePath) && JSON.parse((0, import_fs9.readFileSync)(packagePath, "utf-8")).version || null;
2587
1426
  } catch {
2588
1427
  return null;
2589
1428
  }
2590
- }, getVersion = () => "0.2.0-dev";
1429
+ }, getVersion = () => "0.4.0";
2591
1430
 
2592
1431
  // src/index.ts
2593
- init_logger();
2594
1432
  init_verbose();
1433
+
1434
+ // src/utils/withErrorHandling.ts
1435
+ init_logger();
2595
1436
  function withErrorHandling(fn) {
2596
1437
  return async (...args) => {
2597
1438
  try {
@@ -2601,23 +1442,14 @@ function withErrorHandling(fn) {
2601
1442
  }
2602
1443
  };
2603
1444
  }
1445
+
1446
+ // src/index.ts
2604
1447
  async function main() {
2605
1448
  let program = new import_commander.Command(), version = getVersion();
2606
1449
  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) => {
2607
1450
  setVerboseEnabled(!!thisCommand.opts().verbose);
2608
- }), registerDistributionCommands2(program), program.command("feedback").description("Let us know what you think about Yandex Tracker plugins").action(() => {
2609
- logger_default.info(
2610
- `Help us make Yandex Tracker even better.
2611
- To report bugs or issues, go to: https://forms.yandex.ru/surveys/6767/`
2612
- );
2613
1451
  }), 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(
2614
1452
  "start a tunnel to connect your local code with the app running in the development environment"
2615
- ).option("--no-lint", "skip lint validation").action((options) => withErrorHandling(debug)(options)), program.command("lint").description("run TypeScript and ESLint checks").action(withErrorHandling(lint)), program.command("login").description("authenticate with Yandex Tracker").action(withErrorHandling(login)), program.command("logout").description("remove authentication credentials").action(withErrorHandling(logout)), program.command("whoami").description("display current authentication status").action(withErrorHandling(async () => await whoami())), process.env.USE_TRACKER_TO_PUBLISH ? (program.command("submit").description("build, attach archive to Tracker issue, and submit for review").action(withErrorHandling(submitTracker)), program.command("list").description("list my plugins").action(withErrorHandling(list)), program.command("info [issue-key]").description(
2616
- "get detailed information about a plugin (uses manifest.trackerIssueKey if issue-key not provided)"
2617
- ).action(withErrorHandling(info2))) : (program.command("submit").description("create plugin, upload data, and submit for review").action(withErrorHandling(submitPlatform)), program.command("list").description("list my plugins").action(withErrorHandling(list)), program.command("info [plugin-id]").description(
2618
- "get detailed information about a plugin (uses manifest.id if plugin-id not provided)"
2619
- ).action(withErrorHandling(infoPlatform)), program.command("versions [plugin-id]").description(
2620
- "list all versions of a plugin (uses manifest.id if plugin-id not provided)"
2621
- ).action(withErrorHandling(versions))), process.env.TRACKER_CLI_ADMIN && (program.command("deploy").description("build and upload plugin bundle to S3 for production").action(withErrorHandling(deploy)), program.command("install").description("manage app installations").action(withErrorHandling(install)), program.command("uninstall").description("uninstall app from all slots").action(withErrorHandling(uninstall))), await program.parseAsync(), process.exit(0);
1453
+ ).option("--no-lint", "skip lint validation").action((options) => withErrorHandling(debug)(options)), program.command("lint").description("run TypeScript and ESLint checks").action(withErrorHandling(lint)), registerDistributionCommands2(program), await program.parseAsync(), process.exit(0);
2622
1454
  }
2623
1455
  main();