@weavix/cli 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +2 -1
  2. package/build/index.js +2091 -915
  3. package/build/templates/_external/npmrc.template +1 -0
  4. package/build/templates/_external/src/styles.scss +14 -15
  5. package/build/templates/_internal/npmrc.template +3 -0
  6. package/build/templates/_internal/src/styles.scss +32 -12
  7. package/build/templates/_shared/AGENTS.md +53 -0
  8. package/build/templates/_shared/manifest.schema.json +72 -2
  9. package/build/templates/_shared/package.json +4 -5
  10. package/build/templates/_shared/proxy.ts +111 -0
  11. package/build/templates/_shared/src/main.tsx +1 -1
  12. package/build/templates/_shared/vite.config.ts +3 -1
  13. package/build/templates/attachment.viewer.action/src/App.tsx +1 -5
  14. package/build/templates/board.tab/src/App.tsx +1 -1
  15. package/build/templates/default/src/App.tsx +1 -1
  16. package/build/templates/goal.action/src/App.tsx +2 -2
  17. package/build/templates/goal.block/src/App.tsx +2 -2
  18. package/build/templates/goal.editor.action/index.html +14 -0
  19. package/build/templates/goal.editor.action/src/App.tsx +56 -0
  20. package/build/templates/goal.tab/src/App.tsx +2 -2
  21. package/build/templates/issue.action/src/App.tsx +4 -2
  22. package/build/templates/issue.block/src/App.tsx +2 -2
  23. package/build/templates/issue.comment.action/src/App.tsx +3 -3
  24. package/build/templates/issue.editor.action/index.html +14 -0
  25. package/build/templates/issue.editor.action/src/App.tsx +56 -0
  26. package/build/templates/issue.tab/src/App.tsx +4 -2
  27. package/build/templates/navigation/src/App.tsx +2 -7
  28. package/build/templates/portfolio.action/src/App.tsx +2 -2
  29. package/build/templates/portfolio.block/src/App.tsx +2 -2
  30. package/build/templates/portfolio.editor.action/index.html +14 -0
  31. package/build/templates/portfolio.editor.action/src/App.tsx +56 -0
  32. package/build/templates/portfolio.tab/src/App.tsx +2 -2
  33. package/build/templates/project.action/src/App.tsx +2 -2
  34. package/build/templates/project.block/src/App.tsx +2 -2
  35. package/build/templates/project.editor.action/index.html +14 -0
  36. package/build/templates/project.editor.action/src/App.tsx +56 -0
  37. package/build/templates/project.tab/src/App.tsx +2 -2
  38. package/build/templates/queue.action/index.html +14 -0
  39. package/build/templates/queue.action/src/App.tsx +29 -0
  40. package/build/templates/queue.tab/index.html +14 -0
  41. package/build/templates/queue.tab/src/App.tsx +29 -0
  42. package/build/templates/trigger.action/src/App.tsx +15 -21
  43. package/package.json +2 -1
  44. package/build/templates/_shared/npmrc.template +0 -2
package/build/index.js CHANGED
@@ -38,101 +38,22 @@ var meta_exports = {};
38
38
  __export(meta_exports, {
39
39
  CLI_DESCRIPTION: () => CLI_DESCRIPTION,
40
40
  CLI_HELP_TEXT: () => CLI_HELP_TEXT,
41
- CLI_NAME: () => CLI_NAME
41
+ CLI_NAME: () => CLI_NAME,
42
+ CREATE_SERVICES: () => CREATE_SERVICES
42
43
  });
43
- var CLI_NAME, CLI_DESCRIPTION, CLI_HELP_TEXT, init_meta = __esm({
44
+ var CLI_NAME, CLI_DESCRIPTION, CLI_HELP_TEXT, CREATE_SERVICES, init_meta = __esm({
44
45
  "src/distributions/external/meta.ts"() {
45
46
  "use strict";
46
- CLI_NAME = "weavix", CLI_DESCRIPTION = "Weavix CLI", CLI_HELP_TEXT = "";
47
+ CLI_NAME = "weavix", CLI_DESCRIPTION = "Weavix CLI", CLI_HELP_TEXT = "", CREATE_SERVICES = ["tracker"];
47
48
  }
48
49
  });
49
50
 
50
51
  // src/distribution/meta.ts
51
- var impl, CLI_NAME2, CLI_DESCRIPTION2, CLI_HELP_TEXT2, init_meta2 = __esm({
52
+ var impl, CLI_NAME2, CLI_DESCRIPTION2, CLI_HELP_TEXT2, CREATE_SERVICES2, init_meta2 = __esm({
52
53
  "src/distribution/meta.ts"() {
53
54
  "use strict";
54
55
  init_flag();
55
- impl = (init_meta(), __toCommonJS(meta_exports)), { CLI_NAME: CLI_NAME2, CLI_DESCRIPTION: CLI_DESCRIPTION2, CLI_HELP_TEXT: CLI_HELP_TEXT2 } = impl;
56
- }
57
- });
58
-
59
- // src/commands/submit/options.ts
60
- var import_commander, skipChecksOption, init_options = __esm({
61
- "src/commands/submit/options.ts"() {
62
- "use strict";
63
- import_commander = require("commander"), skipChecksOption = new import_commander.Option(
64
- "--skip-checks",
65
- "skip pre-submit validation (manifest, assets, lint, typecheck, tests, audit)"
66
- );
67
- }
68
- });
69
-
70
- // src/utils/verbose.ts
71
- function setVerboseEnabled(value) {
72
- verboseEnabled = value;
73
- }
74
- function isVerboseEnabled() {
75
- return verboseEnabled;
76
- }
77
- function writeVerboseArtifact(relativePath, content) {
78
- let targetPath = import_path.default.resolve(".tracker-cli-debug", relativePath);
79
- return import_fs.default.mkdirSync(import_path.default.dirname(targetPath), { recursive: !0 }), import_fs.default.writeFileSync(targetPath, content), targetPath;
80
- }
81
- var import_fs, import_path, verboseEnabled, init_verbose = __esm({
82
- "src/utils/verbose.ts"() {
83
- "use strict";
84
- import_fs = __toESM(require("fs")), import_path = __toESM(require("path")), verboseEnabled = !1;
85
- }
86
- });
87
-
88
- // src/utils/logger.ts
89
- function success(message) {
90
- console.info(import_picocolors.default.green(`\u2705 ${message}`)), newLine();
91
- }
92
- function error(messageOrErr, err) {
93
- let message = messageOrErr instanceof Error ? messageOrErr.message : messageOrErr;
94
- console.error(import_picocolors.default.red(`\u274C ${message}`)), err instanceof Error && console.error(import_picocolors.default.red(err.message)), newLine();
95
- }
96
- function warning(message) {
97
- console.warn(import_picocolors.default.yellow(`\u26A0\uFE0F ${message}`)), newLine();
98
- }
99
- function info(message) {
100
- console.info(message), newLine();
101
- }
102
- function verbose(message) {
103
- isVerboseEnabled() && (console.info(import_picocolors.default.dim(message)), newLine());
104
- }
105
- function suggest(command) {
106
- console.info(`Run: ${command}`), newLine();
107
- }
108
- function newLine(count = 1) {
109
- console.info(`
110
- `.repeat(count - 1));
111
- }
112
- function separator(char = "\u2500", length = 60) {
113
- console.info(import_picocolors.default.dim(char.repeat(length))), newLine();
114
- }
115
- function commands(title, data) {
116
- newLine(), console.info(import_picocolors.default.bold(import_picocolors.default.cyan(`${title}:`))), newLine(), data.forEach((cmd) => {
117
- console.info(import_picocolors.default.dim(" $ ") + import_picocolors.default.white(cmd));
118
- }), newLine();
119
- }
120
- var import_picocolors, logger, logger_default, init_logger = __esm({
121
- "src/utils/logger.ts"() {
122
- "use strict";
123
- import_picocolors = __toESM(require("picocolors"));
124
- init_verbose();
125
- logger = {
126
- success,
127
- error,
128
- warning,
129
- info,
130
- verbose,
131
- suggest,
132
- newLine,
133
- separator,
134
- commands
135
- }, logger_default = logger;
56
+ impl = (init_meta(), __toCommonJS(meta_exports)), { CLI_NAME: CLI_NAME2, CLI_DESCRIPTION: CLI_DESCRIPTION2, CLI_HELP_TEXT: CLI_HELP_TEXT2, CREATE_SERVICES: CREATE_SERVICES2 } = impl;
136
57
  }
137
58
  });
138
59
 
@@ -143,256 +64,278 @@ function getConfigPath() {
143
64
  function readConfig() {
144
65
  if (cached !== void 0)
145
66
  return cached;
146
- if (!(0, import_fs2.existsSync)(CONFIG_FILE))
67
+ if (!(0, import_fs.existsSync)(CONFIG_FILE))
147
68
  return cached = null, cached;
148
69
  try {
149
- cached = JSON.parse((0, import_fs2.readFileSync)(CONFIG_FILE, "utf-8"));
70
+ cached = JSON.parse((0, import_fs.readFileSync)(CONFIG_FILE, "utf-8"));
150
71
  } catch {
151
72
  cached = null;
152
73
  }
153
74
  return cached;
154
75
  }
155
76
  function writeConfig(config) {
156
- (0, import_fs2.existsSync)(CONFIG_DIR) || (0, import_fs2.mkdirSync)(CONFIG_DIR, { recursive: !0, mode: 448 }), (0, import_fs2.writeFileSync)(CONFIG_FILE, JSON.stringify(config, null, 2), { mode: 384 }), cached = config;
77
+ (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;
157
78
  }
158
79
  function clearConfig() {
159
- (0, import_fs2.existsSync)(CONFIG_FILE) && (0, import_fs2.rmSync)(CONFIG_FILE), cached = null;
80
+ (0, import_fs.existsSync)(CONFIG_FILE) && (0, import_fs.rmSync)(CONFIG_FILE), cached = null;
160
81
  }
161
- var import_fs2, os, import_path2, CONFIG_DIR, CONFIG_FILE, cached, init_manager = __esm({
82
+ var import_fs, os, import_path, CONFIG_DIR, CONFIG_FILE, cached, init_manager = __esm({
162
83
  "src/core/cliConfig/manager.ts"() {
163
84
  "use strict";
164
- import_fs2 = require("fs"), os = __toESM(require("os")), import_path2 = __toESM(require("path")), CONFIG_DIR = import_path2.default.join(os.homedir(), ".tracker-cli"), CONFIG_FILE = import_path2.default.join(CONFIG_DIR, "config.json");
85
+ import_fs = require("fs"), os = __toESM(require("os")), import_path = __toESM(require("path")), CONFIG_DIR = import_path.default.join(os.homedir(), ".yaweavix"), CONFIG_FILE = import_path.default.join(CONFIG_DIR, "config.json");
165
86
  }
166
87
  });
167
88
 
168
- // src/core/cliConfig/registerCommand.ts
169
- async function promptString(message, current) {
170
- return (await (0, import_prompts.input)({
171
- message: current ? `${message} (current: ${current})` : `${message} (optional)`,
172
- default: current,
173
- required: !1
174
- }))?.trim() || void 0;
175
- }
176
- async function runConfigSet(cliName) {
177
- let existing = readConfig() ?? {};
178
- logger_default.info(
179
- "Configure CLI overrides. Empty input clears the value (and falls back to defaults where applicable)."
180
- );
181
- 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(
182
- "Production bucket (static)",
183
- existing.buckets?.production?.static
184
- ), productionConfig = await promptString(
185
- "Production bucket (config)",
186
- existing.buckets?.production?.config
187
- ), pluginDownloadProduction = await promptString(
188
- "Plugin download base URL",
189
- existing.pluginDownloadBase?.production
190
- ), platformBaseUrl = await promptString(
191
- "Platform API base URL",
192
- existing.api?.platformBaseUrl
193
- ), oauthUrl = await promptString("OAuth token URL", existing.auth?.oauthUrl);
194
- writeConfig({
195
- s3: { endpoint: s3Endpoint, region: s3Region },
196
- mds: { endpoint: mdsEndpoint },
197
- buckets: {
198
- production: { static: productionStatic, config: productionConfig }
199
- },
200
- pluginDownloadBase: { production: pluginDownloadProduction },
201
- api: { platformBaseUrl },
202
- auth: { oauthUrl }
203
- }), logger_default.success(`Configuration saved \u2192 ${getConfigPath()}`), logger_default.info(`Inspect with "${cliName} config show" or revert with "${cliName} config clear".`);
204
- }
205
- function runConfigShow(cliName) {
206
- let cfg = readConfig();
207
- if (!cfg) {
208
- logger_default.info(
209
- `No configuration found at ${getConfigPath()}. Run "${cliName} config set" to create one.`
210
- );
211
- return;
212
- }
213
- logger_default.info(`Configuration at ${getConfigPath()}:`), logger_default.info(JSON.stringify(cfg, null, 2));
214
- }
215
- function runConfigClear() {
216
- clearConfig(), logger_default.success(`Configuration removed (${getConfigPath()})`);
217
- }
218
- function registerConfigCommand(program, cliName) {
219
- let config = program.command("config").description("manage CLI configuration");
220
- 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);
89
+ // src/core/doctor/policy.ts
90
+ function createDoctorPolicy(options) {
91
+ let publish = !!options.publish, publishOnlyStatus = publish ? "fail" : "warn";
92
+ return {
93
+ mode: publish ? "publish" : "debug",
94
+ marketplaceAssetsStatus: publishOnlyStatus,
95
+ manifestPermissionsStatus: publishOnlyStatus,
96
+ manifestSupportStatus: publishOnlyStatus,
97
+ distMissingStatus: publishOnlyStatus,
98
+ authMissingStatus: publishOnlyStatus
99
+ };
221
100
  }
222
- var import_prompts, init_registerCommand = __esm({
223
- "src/core/cliConfig/registerCommand.ts"() {
101
+ var init_policy = __esm({
102
+ "src/core/doctor/policy.ts"() {
224
103
  "use strict";
225
- import_prompts = require("@inquirer/prompts");
226
- init_logger();
227
- init_manager();
228
104
  }
229
105
  });
230
106
 
231
- // src/utils/withErrorHandling.ts
232
- function withErrorHandling(fn) {
233
- return async (...args) => {
234
- try {
235
- await fn(...args);
236
- } catch (error2) {
237
- error2 instanceof Error && error2.name === "ExitPromptError" && process.exit(0), logger_default.error(error2), process.exit(1);
238
- }
107
+ // src/core/doctor/report.ts
108
+ function createDoctorReport() {
109
+ return {
110
+ ok: !1,
111
+ summary: {
112
+ passed: 0,
113
+ warnings: 0,
114
+ failures: 0
115
+ },
116
+ checks: []
239
117
  };
240
118
  }
241
- var init_withErrorHandling = __esm({
242
- "src/utils/withErrorHandling.ts"() {
119
+ function addCheck(report, check) {
120
+ report.checks.push({
121
+ ...check,
122
+ status: check.status || "pass"
123
+ });
124
+ }
125
+ function updateSummary(report) {
126
+ let passed = report.checks.filter((check) => check.status === "pass").length, warnings = report.checks.filter((check) => check.status === "warn").length, failures = report.checks.filter((check) => check.status === "fail").length;
127
+ report.summary = {
128
+ passed,
129
+ warnings,
130
+ failures
131
+ }, report.ok = failures === 0;
132
+ }
133
+ function statusBadge(status) {
134
+ let display = STATUS_DISPLAY[status];
135
+ return `${display.icon} [${display.label}]`;
136
+ }
137
+ function formatReport(report) {
138
+ let lines = ["Tracker Plugin Doctor", ""];
139
+ report.distribution && lines.push(`Distribution: ${report.distribution}`), report.mode && lines.push(`Mode: ${report.mode}`), report.projectRoot && lines.push(`Project root: ${report.projectRoot}`), report.manifestPath && lines.push(`Manifest path: ${report.manifestPath}`), report.manifest && lines.push(`Manifest: ${report.manifest.slug}@${report.manifest.version}`), report.packageManager && lines.push(`Package manager: ${report.packageManager}`), lines.push("", "Checks:");
140
+ for (let check of report.checks)
141
+ lines.push(` ${statusBadge(check.status)} ${check.title}: ${check.message}`), check.action && lines.push(` Action: ${check.action}`);
142
+ return lines.push(
143
+ "",
144
+ `Summary: \u2713 ${report.summary.passed} passed, \u26A0 ${report.summary.warnings} warning(s), \u2717 ${report.summary.failures} failure(s).`
145
+ ), lines.push(
146
+ report.ok ? report.summary.warnings > 0 ? "\u26A0 Doctor finished with warnings." : "\u2713 Doctor finished successfully." : report.mode === "publish" ? "\u2717 Doctor failed. Fix failed checks before publishing." : "\u2717 Doctor failed. Fix failed checks before local debug or build."
147
+ ), `${lines.join(`
148
+ `)}
149
+ `;
150
+ }
151
+ function writeStdout(content) {
152
+ return new Promise((resolve2, reject) => {
153
+ process.stdout.write(content, (error2) => {
154
+ if (error2) {
155
+ reject(error2);
156
+ return;
157
+ }
158
+ resolve2();
159
+ });
160
+ });
161
+ }
162
+ async function finishDoctor(report, options) {
163
+ updateSummary(report), await writeStdout(options.json ? `${JSON.stringify(report, null, 4)}
164
+ ` : formatReport(report)), report.ok || (process.exitCode = 1);
165
+ }
166
+ var STATUS_DISPLAY, init_report = __esm({
167
+ "src/core/doctor/report.ts"() {
243
168
  "use strict";
244
- init_logger();
169
+ STATUS_DISPLAY = {
170
+ pass: { icon: "\u2713", label: "PASS" },
171
+ warn: { icon: "\u26A0", label: "WARN" },
172
+ fail: { icon: "\u2717", label: "FAIL" }
173
+ };
245
174
  }
246
175
  });
247
176
 
248
- // src/core/pluginState/pluginStateManager.ts
249
- var import_fs3, import_promises, STATE_FILE, load, save, update, pluginStateManager, init_pluginStateManager = __esm({
250
- "src/core/pluginState/pluginStateManager.ts"() {
177
+ // src/core/auth/keyringAuthStorage.ts
178
+ var fs, import_keyring, parseAuthData, readLegacyAuthData, removeLegacyAuthData, createKeyringAuthStorage, init_keyringAuthStorage = __esm({
179
+ "src/core/auth/keyringAuthStorage.ts"() {
251
180
  "use strict";
252
- import_fs3 = require("fs"), import_promises = require("fs/promises"), STATE_FILE = ".tracker-plugin", load = async () => {
253
- if (!(0, import_fs3.existsSync)(STATE_FILE))
254
- return {};
181
+ fs = __toESM(require("fs")), import_keyring = require("@napi-rs/keyring"), parseAuthData = (value) => !value || typeof value != "object" || !("token" in value) || typeof value.token != "string" || !value.token ? null : {
182
+ token: value.token
183
+ }, readLegacyAuthData = (legacyAuthFile) => {
255
184
  try {
256
- let content = await (0, import_promises.readFile)(STATE_FILE, "utf8");
257
- return JSON.parse(content);
185
+ if (!fs.existsSync(legacyAuthFile))
186
+ return null;
187
+ let data = fs.readFileSync(legacyAuthFile, "utf-8");
188
+ return parseAuthData(JSON.parse(data));
258
189
  } catch {
259
- return {};
190
+ return null;
260
191
  }
261
- }, save = async (state) => {
192
+ }, removeLegacyAuthData = (legacyAuthFile) => {
262
193
  try {
263
- let content = JSON.stringify(state, null, 4);
264
- await (0, import_promises.writeFile)(STATE_FILE, content, "utf8");
265
- } catch (error2) {
266
- throw error2 instanceof Error ? new Error(`Error saving ${STATE_FILE}: ${error2.message}`) : new Error(`Error saving ${STATE_FILE}`);
194
+ fs.existsSync(legacyAuthFile) && fs.unlinkSync(legacyAuthFile);
195
+ } catch {
267
196
  }
268
- }, update = async (updates) => {
269
- let updated = { ...await load(), ...updates };
270
- return await save(updated), updated;
271
- }, pluginStateManager = {
272
- load,
273
- save,
274
- update
197
+ }, createKeyringAuthStorage = ({
198
+ service,
199
+ account,
200
+ legacyAuthFile
201
+ }) => {
202
+ let createEntry = () => new import_keyring.Entry(service, account);
203
+ return {
204
+ getData: () => {
205
+ try {
206
+ let token = createEntry().getPassword();
207
+ if (token)
208
+ return { token };
209
+ } catch {
210
+ return null;
211
+ }
212
+ let legacyAuthData = readLegacyAuthData(legacyAuthFile);
213
+ if (!legacyAuthData)
214
+ return null;
215
+ try {
216
+ createEntry().setPassword(legacyAuthData.token), removeLegacyAuthData(legacyAuthFile);
217
+ } catch {
218
+ return null;
219
+ }
220
+ return legacyAuthData;
221
+ },
222
+ saveAuthData: (token) => {
223
+ createEntry().setPassword(token), removeLegacyAuthData(legacyAuthFile);
224
+ },
225
+ removeAuthData: () => {
226
+ try {
227
+ createEntry().deletePassword();
228
+ } catch {
229
+ }
230
+ removeLegacyAuthData(legacyAuthFile);
231
+ }
232
+ };
275
233
  };
276
234
  }
277
235
  });
278
236
 
279
- // src/api/utils.ts
280
- function getIssueStatusLabel(issue) {
281
- let { key: statusKey, display: statusDisplay } = issue.status;
282
- return statusKey === "closed" && issue.resolution?.display ? issue.resolution.display : statusDisplay ?? statusKey;
283
- }
284
- function getIssueStatusCategory(issue) {
285
- let statusKey = issue.status.key, resolutionKey = issue.resolution?.key;
286
- if (statusKey === "closed")
287
- return resolutionKey === "agreed" ? "approved" : resolutionKey === "rejected" || resolutionKey === "declined" ? "rejected" : "neutral";
288
- switch (statusKey) {
289
- case "waitingForApprove":
290
- case "inProgress":
291
- return "pending";
292
- case "resultAcceptance":
293
- return "acceptance";
294
- case "testing":
295
- return "testing";
296
- case "need_info":
297
- return "need_info";
298
- default:
299
- return "neutral";
300
- }
301
- }
302
- var init_utils = __esm({
303
- "src/api/utils.ts"() {
237
+ // src/distributions/external/authManager.ts
238
+ var os2, path2, authFile, authStorage, getToken, externalAuthManager, init_authManager = __esm({
239
+ "src/distributions/external/authManager.ts"() {
304
240
  "use strict";
241
+ os2 = __toESM(require("os")), path2 = __toESM(require("path"));
242
+ init_keyringAuthStorage();
243
+ authFile = path2.join(os2.homedir(), ".weavix", "auth.json"), authStorage = createKeyringAuthStorage({
244
+ service: "weavix",
245
+ account: "oauth-token",
246
+ legacyAuthFile: authFile
247
+ }), getToken = () => authStorage.getData()?.token ?? null, externalAuthManager = {
248
+ get token() {
249
+ return getToken();
250
+ },
251
+ get data() {
252
+ return authStorage.getData();
253
+ },
254
+ saveAuthData: authStorage.saveAuthData,
255
+ removeAuthData: authStorage.removeAuthData
256
+ };
305
257
  }
306
258
  });
307
259
 
308
- // src/utils/pluginDisplay.ts
309
- function showTrackerPluginList(issues) {
310
- if (!issues || issues.length === 0) {
311
- console.info(import_picocolors2.default.dim(" No plugins found")), logger_default.newLine();
312
- return;
313
- }
314
- printHeader(`\u{1F4CB} Your Plugins \xB7 ${issues.length}`), logger_default.newLine(), issues.forEach((issue) => {
315
- let slugMatch = issue.summary.match(/^Plugin:\s*(.+)$/), slug = slugMatch ? import_picocolors2.default.magenta(slugMatch[1].trim()) : import_picocolors2.default.dim(issue.summary), statusBadge = getTrackerIssueBadge(issue);
316
- console.info(
317
- ` ${slug} ${import_picocolors2.default.dim("\xB7")} ${statusBadge} ${import_picocolors2.default.dim("\xB7")} ${import_picocolors2.default.dim(issue.key)}`
318
- ), logger_default.newLine();
319
- });
260
+ // src/distributions/external/hosts.ts
261
+ var hosts_exports = {};
262
+ __export(hosts_exports, {
263
+ getBuckets: () => getBuckets,
264
+ getMdsEndpoint: () => getMdsEndpoint,
265
+ getOAuthTokenUrl: () => getOAuthTokenUrl,
266
+ getPlatformBaseUrl: () => getPlatformBaseUrl,
267
+ getPluginDownloadBase: () => getPluginDownloadBase,
268
+ getS3Endpoint: () => getS3Endpoint,
269
+ getS3Region: () => getS3Region,
270
+ getTrackerBaseUrl: () => getTrackerBaseUrl,
271
+ getUpdateCheckInfo: () => getUpdateCheckInfo
272
+ });
273
+ function requireConfig() {
274
+ let cfg = readConfig();
275
+ if (!cfg)
276
+ throw new Error('CLI is not configured. Run "weavix config set" to configure.');
277
+ return cfg;
320
278
  }
321
- function showTrackerPluginInfo(issue) {
322
- printHeader("\u{1F4E6} Plugin"), logger_default.newLine(), printField("Issue key", import_picocolors2.default.cyan(issue.key)), printField("Status", getTrackerIssueBadge(issue)), printField("Summary", import_picocolors2.default.white(issue.summary)), issue.createdAt && printCreated(issue.createdAt), issue.updatedAt && printUpdated(issue.updatedAt);
279
+ function getS3Endpoint() {
280
+ let cfg = requireConfig();
281
+ if (!cfg.s3?.endpoint)
282
+ throw new Error('S3 endpoint is not configured. Run "weavix config set" to configure.');
283
+ return cfg.s3.endpoint;
323
284
  }
324
- var import_picocolors2, printHeader, getTrackerIssueBadge, formatDate, printField, printCreated, printUpdated, init_pluginDisplay = __esm({
325
- "src/utils/pluginDisplay.ts"() {
326
- "use strict";
327
- import_picocolors2 = __toESM(require("picocolors"));
328
- init_utils();
329
- init_logger();
330
- printHeader = (title) => {
331
- console.info(import_picocolors2.default.bold(import_picocolors2.default.white(title)));
332
- }, getTrackerIssueBadge = (issue) => {
333
- let label = getIssueStatusLabel(issue);
334
- switch (getIssueStatusCategory(issue)) {
335
- case "approved":
336
- return import_picocolors2.default.black(import_picocolors2.default.bgGreen(` ${label} `));
337
- case "rejected":
338
- return import_picocolors2.default.white(import_picocolors2.default.bgRed(` ${label} `));
339
- case "pending":
340
- return import_picocolors2.default.black(import_picocolors2.default.bgYellow(` ${label} `));
341
- case "acceptance":
342
- return import_picocolors2.default.black(import_picocolors2.default.bgCyan(` ${label} `));
343
- case "testing":
344
- return import_picocolors2.default.black(import_picocolors2.default.bgMagenta(` ${label} `));
345
- case "need_info":
346
- return import_picocolors2.default.black(import_picocolors2.default.bgBlue(` ${label} `));
347
- default:
348
- return import_picocolors2.default.black(import_picocolors2.default.bgWhite(` ${label} `));
349
- }
350
- }, formatDate = (dateString) => dateString ? new Date(dateString).toLocaleString("ru-RU", {
351
- year: "numeric",
352
- month: "2-digit",
353
- day: "2-digit",
354
- hour: "2-digit",
355
- minute: "2-digit"
356
- }) : "-", printField = (label, value, minWidth = 12) => {
357
- console.info(` ${import_picocolors2.default.dim(label.padEnd(minWidth))} ${value}`);
358
- }, printCreated = (createdAt) => {
359
- printField("Created", import_picocolors2.default.white(formatDate(createdAt)));
360
- }, printUpdated = (updatedAt) => {
361
- printField("Updated", import_picocolors2.default.white(formatDate(updatedAt)));
362
- };
363
- }
364
- });
365
-
366
- // src/distributions/external/authManager.ts
367
- var fs2, os2, path3, authDir, authFile, getData, getToken, saveAuthData, removeAuthData, externalAuthManager, init_authManager = __esm({
368
- "src/distributions/external/authManager.ts"() {
285
+ function getMdsEndpoint() {
286
+ let cfg = requireConfig();
287
+ if (!cfg.mds?.endpoint)
288
+ throw new Error('MDS endpoint is not configured. Run "weavix config set" to configure.');
289
+ return cfg.mds.endpoint;
290
+ }
291
+ function getS3Region() {
292
+ let cfg = requireConfig();
293
+ if (!cfg.s3?.region)
294
+ throw new Error('S3 region is not configured. Run "weavix config set" to configure.');
295
+ return cfg.s3.region;
296
+ }
297
+ function getBuckets() {
298
+ let production = requireConfig().buckets?.production;
299
+ if (!production?.static || !production?.config)
300
+ throw new Error('S3 buckets are not configured. Run "weavix config set" to configure.');
301
+ let prod = { static: production.static, config: production.config };
302
+ return { testing: prod, production: prod };
303
+ }
304
+ function getPluginDownloadBase(env) {
305
+ if (env === "debug")
306
+ return "http://localhost:5173/plugins-debug";
307
+ let base = requireConfig().pluginDownloadBase?.production;
308
+ if (!base)
309
+ throw new Error(
310
+ 'Plugin download base is not configured. Run "weavix config set" to configure.'
311
+ );
312
+ return base;
313
+ }
314
+ function getPlatformBaseUrl() {
315
+ let cfg = requireConfig();
316
+ if (!cfg.api?.platformBaseUrl)
317
+ throw new Error(
318
+ 'Platform API URL is not configured. Run "weavix config set" to configure.'
319
+ );
320
+ return cfg.api.platformBaseUrl;
321
+ }
322
+ function getTrackerBaseUrl() {
323
+ return TRACKER_BASE_URL;
324
+ }
325
+ function getOAuthTokenUrl() {
326
+ let cfg = requireConfig();
327
+ if (!cfg.auth?.oauthUrl)
328
+ throw new Error('OAuth URL is not configured. Run "weavix config set" to configure.');
329
+ return cfg.auth.oauthUrl;
330
+ }
331
+ function getUpdateCheckInfo() {
332
+ return null;
333
+ }
334
+ var TRACKER_BASE_URL, init_hosts = __esm({
335
+ "src/distributions/external/hosts.ts"() {
369
336
  "use strict";
370
- fs2 = __toESM(require("fs")), os2 = __toESM(require("os")), path3 = __toESM(require("path")), authDir = path3.join(os2.homedir(), ".weavix"), authFile = path3.join(authDir, "auth.json"), getData = () => {
371
- try {
372
- if (!fs2.existsSync(authFile))
373
- return null;
374
- let data = fs2.readFileSync(authFile, "utf-8");
375
- return JSON.parse(data);
376
- } catch {
377
- return null;
378
- }
379
- }, getToken = () => getData()?.token ?? null, saveAuthData = (token) => {
380
- let authData = { token };
381
- fs2.existsSync(authDir) || fs2.mkdirSync(authDir, { recursive: !0, mode: 448 }), fs2.writeFileSync(authFile, JSON.stringify(authData, null, 2), {
382
- mode: 384
383
- });
384
- }, removeAuthData = () => {
385
- fs2.existsSync(authFile) && fs2.unlinkSync(authFile);
386
- }, externalAuthManager = {
387
- get token() {
388
- return getToken();
389
- },
390
- get data() {
391
- return getData();
392
- },
393
- saveAuthData,
394
- removeAuthData
395
- };
337
+ init_manager();
338
+ TRACKER_BASE_URL = "https://api.tracker.yandex.net/v3";
396
339
  }
397
340
  });
398
341
 
@@ -422,7 +365,7 @@ async function externalTrackerApiRequest(endpoint, options = {}) {
422
365
  let formHeaders = formData.getHeaders?.();
423
366
  Object.assign(requestHeaders, formHeaders), requestBody = formData;
424
367
  } else body && method !== "GET" && (requestHeaders["Content-Type"] = "application/json", requestBody = JSON.stringify(body));
425
- let queryString = buildQueryString(queryParams), url = `${TRACKER_BASE_URL}${endpoint}${queryString}`, response = await (0, import_node_fetch.default)(url, {
368
+ let queryString = buildQueryString(queryParams), url = `${TRACKER_BASE_URL2}${endpoint}${queryString}`, response = await (0, import_node_fetch.default)(url, {
426
369
  method,
427
370
  headers: requestHeaders,
428
371
  body: requestBody
@@ -438,227 +381,433 @@ async function externalTrackerApiRequest(endpoint, options = {}) {
438
381
  }
439
382
  return parseResponse(response);
440
383
  }
441
- var import_node_fetch, TRACKER_BASE_URL, ORG_ID, init_trackerApiRequest = __esm({
384
+ var import_node_fetch, TRACKER_BASE_URL2, ORG_ID, init_trackerApiRequest = __esm({
442
385
  "src/distributions/external/trackerApiRequest.ts"() {
443
386
  "use strict";
444
387
  import_node_fetch = __toESM(require("node-fetch"));
445
388
  init_authManager();
446
389
  init_meta();
447
- TRACKER_BASE_URL = "https://api.tracker.yandex.net/v3", ORG_ID = "8470884";
390
+ TRACKER_BASE_URL2 = "https://api.tracker.yandex.net/v3", ORG_ID = "8470884";
448
391
  }
449
392
  });
450
393
 
451
- // src/distributions/external/tracker.ts
452
- function buildIssueSummary(slug) {
453
- return `Plugin: ${slug}`;
454
- }
455
- function buildIssueDescription(params) {
456
- let { pluginId, slug, version, manifestJson } = params;
457
- return [
458
- `**Plugin UUID:** ${pluginId}`,
459
- `**Slug:** ${slug}`,
460
- `**Version:** ${version}`,
461
- "",
462
- "**Manifest:**",
463
- "```json",
464
- manifestJson,
465
- "```"
466
- ].join(`
467
- `);
468
- }
469
- async function createPluginIssue(params) {
470
- let { slug, pluginId, version, manifestJson } = params, body = {
471
- queue: PLUGINMOD_QUEUE,
472
- summary: buildIssueSummary(slug),
473
- description: buildIssueDescription({ pluginId, slug, version, manifestJson }),
474
- tags: ["tracker-plugin"]
475
- };
476
- return externalTrackerApiRequest("/issues", {
477
- method: "POST",
478
- body
479
- });
480
- }
481
- async function updatePluginIssue(issueKey, params) {
482
- return externalTrackerApiRequest(`/issues/${issueKey}`, {
483
- method: "PATCH",
484
- body: params
485
- });
486
- }
487
- async function attachFileToIssue(issueKey, fileBuffer, fileName) {
488
- let formData = new import_form_data.default();
489
- return formData.append("file", fileBuffer, {
490
- filename: fileName,
491
- contentType: "application/zip"
492
- }), externalTrackerApiRequest(`/issues/${issueKey}/attachments`, {
493
- method: "POST",
494
- formData
495
- });
496
- }
497
- async function getIssueTransitions(issueKey) {
498
- return externalTrackerApiRequest(`/issues/${issueKey}/transitions`, {
499
- method: "GET"
500
- });
501
- }
502
- async function executeIssueTransition(issueKey, transitionId) {
503
- await externalTrackerApiRequest(
504
- `/issues/${issueKey}/transitions/${transitionId}/_execute`,
505
- {
506
- method: "POST",
507
- body: {}
394
+ // src/distributions/external/doctorChecks.ts
395
+ var doctorChecks_exports = {};
396
+ __export(doctorChecks_exports, {
397
+ checkDistribution: () => checkDistribution
398
+ });
399
+ function checkCliConfig(report) {
400
+ let config = readConfig(), configPath = getConfigPath();
401
+ if (config) {
402
+ addCheck(report, {
403
+ id: "distribution.config",
404
+ title: "CLI config",
405
+ message: `External CLI config is readable at ${configPath}.`,
406
+ data: {
407
+ configPath
408
+ }
409
+ });
410
+ return;
411
+ }
412
+ addCheck(report, {
413
+ id: "distribution.config",
414
+ title: "CLI config",
415
+ status: "fail",
416
+ message: `External CLI config is missing at ${configPath}.`,
417
+ action: "Run weavix config set before using external distribution commands.",
418
+ data: {
419
+ configPath
508
420
  }
509
- );
510
- }
511
- async function getIssue(issueKey) {
512
- return externalTrackerApiRequest(`/issues/${issueKey}`, {
513
- method: "GET"
514
421
  });
515
422
  }
516
- async function addIssueComment(issueKey, text) {
517
- await externalTrackerApiRequest(`/issues/${issueKey}/comments`, {
518
- method: "POST",
519
- body: { text }
520
- });
423
+ function checkHostResolution(report) {
424
+ try {
425
+ let data = {
426
+ trackerBaseUrl: getTrackerBaseUrl(),
427
+ platformBaseUrl: getPlatformBaseUrl(),
428
+ s3Endpoint: getS3Endpoint(),
429
+ mdsEndpoint: getMdsEndpoint(),
430
+ s3Region: getS3Region(),
431
+ buckets: getBuckets(),
432
+ pluginDownloadBase: getPluginDownloadBase("production")
433
+ };
434
+ addCheck(report, {
435
+ id: "distribution.hosts",
436
+ title: "External host configuration",
437
+ message: "External host configuration resolved.",
438
+ data
439
+ });
440
+ } catch (error2) {
441
+ addCheck(report, {
442
+ id: "distribution.hosts",
443
+ title: "External host configuration",
444
+ status: "fail",
445
+ message: error2 instanceof Error ? error2.message : String(error2),
446
+ action: "Run weavix config set and fill required endpoints."
447
+ });
448
+ }
521
449
  }
522
- async function getMyPluginIssues() {
523
- return externalTrackerApiRequest("/issues/_search", {
524
- method: "POST",
525
- body: {
526
- filter: {
527
- queue: "PLUGINMOD",
528
- createdBy: "me()"
450
+ async function checkExternalAuth(report, {
451
+ required,
452
+ useNetwork
453
+ }) {
454
+ let authData = externalAuthManager.data, authStatus = required || useNetwork ? "fail" : "warn";
455
+ if (!authData) {
456
+ addCheck(report, {
457
+ id: "auth.tracker",
458
+ title: "Tracker auth",
459
+ status: authStatus,
460
+ message: "External Tracker auth token is missing in the system credential store.",
461
+ action: "Run weavix login before submit or network diagnostics.",
462
+ data: {
463
+ storage: "system credential store"
529
464
  }
465
+ });
466
+ return;
467
+ }
468
+ if (addCheck(report, {
469
+ id: "auth.tracker",
470
+ title: "Tracker auth",
471
+ message: "External Tracker auth token is available in the system credential store.",
472
+ data: {
473
+ storage: "system credential store"
474
+ }
475
+ }), !!useNetwork)
476
+ try {
477
+ await externalTrackerApiRequest("/myself"), addCheck(report, {
478
+ id: "auth.tracker.network",
479
+ title: "Tracker auth network",
480
+ message: "Verified external Tracker auth with /myself."
481
+ });
482
+ } catch (error2) {
483
+ addCheck(report, {
484
+ id: "auth.tracker.network",
485
+ title: "Tracker auth network",
486
+ status: "fail",
487
+ message: error2 instanceof Error ? error2.message : String(error2),
488
+ action: "Check network access, org access, and rerun weavix login."
489
+ });
530
490
  }
491
+ }
492
+ async function checkDistribution(report, _projectRoot, options, policy = createDoctorPolicy(options)) {
493
+ report.distribution = DISTRIBUTION, checkCliConfig(report), checkHostResolution(report), await checkExternalAuth(report, {
494
+ required: policy.authMissingStatus === "fail",
495
+ useNetwork: !!options.network
531
496
  });
532
497
  }
533
- var import_form_data, PLUGINMOD_QUEUE, init_tracker = __esm({
534
- "src/distributions/external/tracker.ts"() {
498
+ var DISTRIBUTION, init_doctorChecks = __esm({
499
+ "src/distributions/external/doctorChecks.ts"() {
535
500
  "use strict";
536
- import_form_data = __toESM(require("form-data"));
501
+ init_manager();
502
+ init_policy();
503
+ init_report();
504
+ init_authManager();
505
+ init_hosts();
537
506
  init_trackerApiRequest();
538
- PLUGINMOD_QUEUE = "PLUGINMOD";
507
+ DISTRIBUTION = "external";
539
508
  }
540
509
  });
541
510
 
542
- // src/distributions/external/info.ts
543
- async function infoExternal(issueKey) {
544
- let targetIssueKey = issueKey;
545
- if (targetIssueKey || (targetIssueKey = (await pluginStateManager.load()).trackerIssueKey), !targetIssueKey) {
546
- logger_default.warning(
547
- `No issue key provided and plugin has not been submitted yet. Run "${CLI_NAME} submit" first.`
548
- ), logger_default.suggest(`${CLI_NAME} submit`);
511
+ // src/distribution/doctorChecks.ts
512
+ var impl2, checkDistribution2, init_doctorChecks2 = __esm({
513
+ "src/distribution/doctorChecks.ts"() {
514
+ "use strict";
515
+ init_flag();
516
+ impl2 = (init_doctorChecks(), __toCommonJS(doctorChecks_exports)), { checkDistribution: checkDistribution2 } = impl2;
517
+ }
518
+ });
519
+
520
+ // src/core/doctor/distChecks.ts
521
+ function resolveDistEntrypoint(distDir, entrypoint) {
522
+ if (import_path2.default.isAbsolute(entrypoint))
523
+ return {
524
+ error: `${entrypoint} is absolute`
525
+ };
526
+ let filePath = import_path2.default.resolve(distDir, import_path2.default.normalize(entrypoint)), relative = import_path2.default.relative(distDir, filePath);
527
+ return relative.startsWith("..") || import_path2.default.isAbsolute(relative) ? {
528
+ error: `${entrypoint} escapes dist`
529
+ } : {
530
+ filePath
531
+ };
532
+ }
533
+ async function checkDist(report, projectRoot, entries, policy) {
534
+ let distDir = import_path2.default.join(projectRoot, "dist");
535
+ if (!import_fs2.default.existsSync(distDir)) {
536
+ addCheck(report, {
537
+ id: "dist.exists",
538
+ title: "dist directory",
539
+ status: policy.distMissingStatus,
540
+ message: "dist directory is missing.",
541
+ action: "Run the plugin build before publishing."
542
+ });
549
543
  return;
550
544
  }
551
- logger_default.info(`\u23F3 Fetching plugin info for ${targetIssueKey}...`);
552
- try {
553
- let issue = await getIssue(targetIssueKey);
554
- showTrackerPluginInfo(issue);
555
- } catch (error2) {
556
- throw logger_default.error(`Failed to fetch plugin info for ${targetIssueKey}`), error2;
545
+ if (!import_fs2.default.statSync(distDir).isDirectory()) {
546
+ addCheck(report, {
547
+ id: "dist.exists",
548
+ title: "dist directory",
549
+ status: "fail",
550
+ message: `${distDir} exists but is not a directory.`,
551
+ action: "Remove it and run the plugin build."
552
+ });
553
+ return;
554
+ }
555
+ let files = await (0, import_tinyglobby.glob)(["**/*"], {
556
+ cwd: distDir,
557
+ onlyFiles: !0,
558
+ absolute: !0
559
+ });
560
+ files.length === 0 ? addCheck(report, {
561
+ id: "dist.files",
562
+ title: "dist files",
563
+ status: "fail",
564
+ message: "dist directory is empty.",
565
+ action: "Run the plugin build and verify generated files."
566
+ }) : addCheck(report, {
567
+ id: "dist.files",
568
+ title: "dist files",
569
+ message: `dist contains ${files.length} file(s).`
570
+ });
571
+ let entrypoints = [...new Set(entries.map((entry) => entry.entrypoint))], invalidEntrypoints = [], missingEntrypoints = [];
572
+ for (let entrypoint of entrypoints) {
573
+ let resolved = resolveDistEntrypoint(distDir, entrypoint);
574
+ if (resolved.error || !resolved.filePath) {
575
+ invalidEntrypoints.push(
576
+ resolved.error ? `${entrypoint} (${resolved.error})` : entrypoint
577
+ );
578
+ continue;
579
+ }
580
+ (!import_fs2.default.existsSync(resolved.filePath) || !import_fs2.default.statSync(resolved.filePath).isFile()) && missingEntrypoints.push(entrypoint);
557
581
  }
582
+ invalidEntrypoints.length > 0 ? addCheck(report, {
583
+ id: "dist.entrypoints.valid",
584
+ title: "Built entrypoint paths",
585
+ status: "fail",
586
+ message: `Invalid entrypoint path(s): ${invalidEntrypoints.join(", ")}.`,
587
+ action: "Use relative entrypoint paths inside dist, for example index.html."
588
+ }) : entrypoints.length > 0 && addCheck(report, {
589
+ id: "dist.entrypoints.valid",
590
+ title: "Built entrypoint paths",
591
+ message: "Manifest entrypoint paths stay inside dist."
592
+ }), missingEntrypoints.length > 0 ? addCheck(report, {
593
+ id: "dist.entrypoints.exist",
594
+ title: "Built entrypoints",
595
+ status: "fail",
596
+ message: `Missing built entrypoint file(s): ${missingEntrypoints.join(", ")}.`,
597
+ action: "Run the plugin build and keep manifest entrypoint values in sync."
598
+ }) : entrypoints.length > 0 && invalidEntrypoints.length === 0 && addCheck(report, {
599
+ id: "dist.entrypoints.exist",
600
+ title: "Built entrypoints",
601
+ message: "All manifest entrypoints exist in dist."
602
+ });
558
603
  }
559
- var init_info = __esm({
560
- "src/distributions/external/info.ts"() {
604
+ var import_fs2, import_path2, import_tinyglobby, init_distChecks = __esm({
605
+ "src/core/doctor/distChecks.ts"() {
561
606
  "use strict";
562
- init_pluginStateManager();
563
- init_logger();
564
- init_pluginDisplay();
565
- init_meta();
566
- init_tracker();
607
+ import_fs2 = __toESM(require("fs")), import_path2 = __toESM(require("path")), import_tinyglobby = require("tinyglobby");
608
+ init_report();
567
609
  }
568
610
  });
569
611
 
570
- // src/distributions/external/list.ts
571
- async function listExternal() {
572
- logger_default.info("\u23F3 Fetching my plugins from Tracker...");
573
- try {
574
- let issues = await getMyPluginIssues();
575
- showTrackerPluginList(issues);
576
- } catch (error2) {
577
- throw logger_default.error("Failed to fetch plugins list"), error2;
612
+ // ../tracker-core/src/types/slots.ts
613
+ var TRACKER_SLOTS, init_slots = __esm({
614
+ "../tracker-core/src/types/slots.ts"() {
615
+ "use strict";
616
+ TRACKER_SLOTS = [
617
+ "issue.action",
618
+ "issue.block",
619
+ "issue.tab",
620
+ "issue.comment.action",
621
+ "issue.editor.action",
622
+ "queue.action",
623
+ "queue.tab",
624
+ "navigation",
625
+ "trigger.create.action",
626
+ "trigger.edit.action",
627
+ "project.action",
628
+ "project.block",
629
+ "project.tab",
630
+ "project.editor.action",
631
+ "portfolio.action",
632
+ "portfolio.block",
633
+ "portfolio.tab",
634
+ "portfolio.editor.action",
635
+ "goal.action",
636
+ "goal.block",
637
+ "goal.tab",
638
+ "goal.editor.action",
639
+ "attachment.viewer.action",
640
+ "board.tab"
641
+ ];
578
642
  }
579
- }
580
- var init_list = __esm({
581
- "src/distributions/external/list.ts"() {
643
+ });
644
+
645
+ // ../tracker-core/src/index.ts
646
+ var init_src = __esm({
647
+ "../tracker-core/src/index.ts"() {
582
648
  "use strict";
583
- init_logger();
584
- init_pluginDisplay();
585
- init_tracker();
649
+ init_slots();
586
650
  }
587
651
  });
588
652
 
589
- // src/distributions/external/login.ts
590
- async function loginExternal() {
591
- console.info(
592
- import_picocolors3.default.dim(
593
- "To get an OAuth token for Yandex Tracker, please contact Tracker support and request one."
594
- )
595
- ), console.info("");
596
- let trimmed = (await (0, import_prompts2.input)({
597
- message: "Enter your OAuth token:",
598
- required: !0
599
- })).trim();
600
- externalAuthManager.saveAuthData(trimmed), logger_default.success("OAuth token saved successfully."), logger_default.info('You can now use "weavix submit" to submit your plugin for review.');
601
- }
602
- function logoutExternal() {
603
- if (!externalAuthManager.data) {
604
- logger_default.warning("You are not logged in.");
605
- return;
606
- }
607
- externalAuthManager.removeAuthData(), logger_default.success("Successfully logged out.");
608
- }
609
- var import_prompts2, import_picocolors3, init_login = __esm({
610
- "src/distributions/external/login.ts"() {
611
- "use strict";
612
- import_prompts2 = require("@inquirer/prompts"), import_picocolors3 = __toESM(require("picocolors"));
613
- init_logger();
614
- init_authManager();
615
- }
616
- });
617
-
618
- // src/utils/execCommand.ts
619
- var import_execa, execCommand, init_execCommand = __esm({
620
- "src/utils/execCommand.ts"() {
621
- "use strict";
622
- import_execa = require("execa"), execCommand = async (command, cwd = process.cwd(), env) => {
623
- await (0, import_execa.execa)(command, {
624
- cwd,
625
- shell: !0,
626
- stdio: "inherit",
627
- env: env ? { ...process.env, ...env } : void 0
628
- });
629
- };
630
- }
631
- });
632
-
633
- // src/commands/constants/templateCommands.ts
634
- var pluginCmd, init_templateCommands = __esm({
635
- "src/commands/constants/templateCommands.ts"() {
636
- "use strict";
637
- pluginCmd = {
638
- install: "npm install",
639
- build: "npm run build",
640
- dev: "npm run dev",
641
- lint: "npm run lint",
642
- typecheck: "npm run typecheck",
643
- test: "npm test",
644
- audit: "npm audit --audit-level=critical"
645
- };
646
- }
647
- });
648
-
649
- // src/commands/build.ts
650
- var build, init_build = __esm({
651
- "src/commands/build.ts"() {
653
+ // src/core/manifest/constants.ts
654
+ var DATA_PERMISSIONS, TOP_DATA_PERMISSIONS, SERVICES, TEMPLATES, CLI_ONLY_TRACKER_SLOTS, TRACKER_SERVICE_SLOTS, MESSENGER_SERVICE_SLOTS, SERVICE_SLOTS, TEMPLATE_SLOTS, TEMPLATE_SERVICE, init_constants = __esm({
655
+ "src/core/manifest/constants.ts"() {
652
656
  "use strict";
653
- init_execCommand();
654
- init_logger();
655
- init_templateCommands();
656
- build = async ({ environment = "production" } = {}) => {
657
- logger_default.info("\u{1F528} Building project..."), await execCommand(pluginCmd.install), await execCommand(
658
- pluginCmd.build,
659
- process.cwd(),
660
- environment ? { VITE_DEPLOY_ENV: environment } : void 0
661
- );
657
+ init_src();
658
+ DATA_PERMISSIONS = [
659
+ // top 10
660
+ "tracker:issues:read",
661
+ "tracker:issues:write",
662
+ "tracker:issuetypes:read",
663
+ "tracker:statuses:read",
664
+ "tracker:queues:read",
665
+ "tracker:fields:read",
666
+ "tracker:entities:read",
667
+ "tracker:attachments:read",
668
+ "tracker:attachments:write",
669
+ // in alphabetical order
670
+ "tracker:applications:read",
671
+ "tracker:boards:read",
672
+ "tracker:boards:write",
673
+ "tracker:bulk:read",
674
+ "tracker:bulk:write",
675
+ "tracker:bulkchange:read",
676
+ "tracker:bulkchange:write",
677
+ "tracker:charts:read",
678
+ "tracker:commentTemplates:read",
679
+ "tracker:commentTemplates:write",
680
+ "tracker:components:read",
681
+ "tracker:components:write",
682
+ "tracker:data:read",
683
+ "tracker:departments:read",
684
+ "tracker:entities:write",
685
+ "tracker:externalEventTypes:write",
686
+ "tracker:externalEvents:write",
687
+ "tracker:fields:write",
688
+ "tracker:filterFolders:write",
689
+ "tracker:filters:read",
690
+ "tracker:filters:write",
691
+ "tracker:goals:read",
692
+ "tracker:goals:write",
693
+ "tracker:groups:read",
694
+ "tracker:issueTemplates:read",
695
+ "tracker:issueTemplates:write",
696
+ "tracker:links:read",
697
+ "tracker:linktypes:read",
698
+ "tracker:liveBoards:write",
699
+ "tracker:localFields:read",
700
+ "tracker:maillists:read",
701
+ "tracker:maillists:write",
702
+ "tracker:myself:read",
703
+ "tracker:myself:write",
704
+ "tracker:priorities:read",
705
+ "tracker:queues:write",
706
+ "tracker:reminders:read",
707
+ "tracker:reminders:write",
708
+ "tracker:remotelinks:read",
709
+ "tracker:reports:read",
710
+ "tracker:reports:write",
711
+ "tracker:resolutions:read",
712
+ "tracker:resources:read",
713
+ "tracker:resources:write",
714
+ "tracker:roles:read",
715
+ "tracker:screens:read",
716
+ "tracker:services:read",
717
+ "tracker:sprints:read",
718
+ "tracker:sprints:write",
719
+ "tracker:system:write",
720
+ "tracker:tags:read",
721
+ "tracker:translations:read",
722
+ "tracker:users:read",
723
+ "tracker:users:write",
724
+ "tracker:versions:read",
725
+ "tracker:versions:write",
726
+ "tracker:workflows:read",
727
+ "tracker:workflows:write",
728
+ "tracker:worklog:read",
729
+ "tracker:worklog:write"
730
+ ], TOP_DATA_PERMISSIONS = DATA_PERMISSIONS.slice(0, 10), SERVICES = ["tracker", "messenger"], TEMPLATES = [
731
+ "default",
732
+ "issue.action",
733
+ "issue.block",
734
+ "issue.tab",
735
+ "issue.comment.action",
736
+ "issue.editor.action",
737
+ "queue.action",
738
+ "queue.tab",
739
+ "navigation",
740
+ "trigger.action",
741
+ "project.action",
742
+ "project.block",
743
+ "project.tab",
744
+ "project.editor.action",
745
+ "portfolio.action",
746
+ "portfolio.block",
747
+ "portfolio.tab",
748
+ "portfolio.editor.action",
749
+ "goal.action",
750
+ "goal.block",
751
+ "goal.tab",
752
+ "goal.editor.action",
753
+ "attachment.viewer.action",
754
+ "board.tab",
755
+ "user-card-info",
756
+ "user-card-calendar"
757
+ ], CLI_ONLY_TRACKER_SLOTS = ["dock"], TRACKER_SERVICE_SLOTS = [...TRACKER_SLOTS, ...CLI_ONLY_TRACKER_SLOTS], MESSENGER_SERVICE_SLOTS = ["user.card.info"], SERVICE_SLOTS = [...TRACKER_SERVICE_SLOTS, ...MESSENGER_SERVICE_SLOTS], TEMPLATE_SLOTS = {
758
+ default: [],
759
+ "issue.action": ["issue.action"],
760
+ "issue.block": ["issue.block"],
761
+ "issue.tab": ["issue.tab"],
762
+ "issue.comment.action": ["issue.comment.action"],
763
+ "issue.editor.action": ["issue.editor.action"],
764
+ "queue.action": ["queue.action"],
765
+ "queue.tab": ["queue.tab"],
766
+ navigation: ["navigation"],
767
+ "trigger.action": ["trigger.create.action", "trigger.edit.action"],
768
+ "project.action": ["project.action"],
769
+ "project.block": ["project.block"],
770
+ "project.tab": ["project.tab"],
771
+ "project.editor.action": ["project.editor.action"],
772
+ "portfolio.action": ["portfolio.action"],
773
+ "portfolio.block": ["portfolio.block"],
774
+ "portfolio.tab": ["portfolio.tab"],
775
+ "portfolio.editor.action": ["portfolio.editor.action"],
776
+ "goal.action": ["goal.action"],
777
+ "goal.block": ["goal.block"],
778
+ "goal.tab": ["goal.tab"],
779
+ "goal.editor.action": ["goal.editor.action"],
780
+ "attachment.viewer.action": ["attachment.viewer.action"],
781
+ "board.tab": ["board.tab"],
782
+ "user-card-info": ["user.card.info"],
783
+ "user-card-calendar": ["user.card.info"]
784
+ }, TEMPLATE_SERVICE = {
785
+ default: "tracker",
786
+ "issue.action": "tracker",
787
+ "issue.block": "tracker",
788
+ "issue.tab": "tracker",
789
+ "issue.comment.action": "tracker",
790
+ "issue.editor.action": "tracker",
791
+ "queue.action": "tracker",
792
+ "queue.tab": "tracker",
793
+ navigation: "tracker",
794
+ "trigger.action": "tracker",
795
+ "project.action": "tracker",
796
+ "project.block": "tracker",
797
+ "project.tab": "tracker",
798
+ "project.editor.action": "tracker",
799
+ "portfolio.action": "tracker",
800
+ "portfolio.block": "tracker",
801
+ "portfolio.tab": "tracker",
802
+ "portfolio.editor.action": "tracker",
803
+ "goal.action": "tracker",
804
+ "goal.block": "tracker",
805
+ "goal.tab": "tracker",
806
+ "goal.editor.action": "tracker",
807
+ "attachment.viewer.action": "tracker",
808
+ "board.tab": "tracker",
809
+ "user-card-info": "messenger",
810
+ "user-card-calendar": "messenger"
662
811
  };
663
812
  }
664
813
  });
@@ -676,11 +825,11 @@ var permissionsSchemaExtensions, init_manifestPermissionsSchema = __esm({
676
825
  });
677
826
 
678
827
  // src/distribution/manifestPermissionsSchema.ts
679
- var impl2, permissionsSchemaExtensions2, init_manifestPermissionsSchema2 = __esm({
828
+ var impl3, permissionsSchemaExtensions2, init_manifestPermissionsSchema2 = __esm({
680
829
  "src/distribution/manifestPermissionsSchema.ts"() {
681
830
  "use strict";
682
831
  init_flag();
683
- impl2 = (init_manifestPermissionsSchema(), __toCommonJS(manifestPermissionsSchema_exports)), { permissionsSchemaExtensions: permissionsSchemaExtensions2 } = impl2;
832
+ impl3 = (init_manifestPermissionsSchema(), __toCommonJS(manifestPermissionsSchema_exports)), { permissionsSchemaExtensions: permissionsSchemaExtensions2 } = impl3;
684
833
  }
685
834
  });
686
835
 
@@ -712,14 +861,14 @@ var priorityOrder, errorMessages, getPriority, formatValidationErrors, init_form
712
861
  }, formatValidationErrors = (errors) => {
713
862
  let errorsByPath = {};
714
863
  for (let error2 of errors) {
715
- let path18 = error2.instancePath || "root";
716
- errorsByPath[path18] || (errorsByPath[path18] = []), errorsByPath[path18].push(error2);
864
+ let path24 = error2.instancePath || "root";
865
+ errorsByPath[path24] || (errorsByPath[path24] = []), errorsByPath[path24].push(error2);
717
866
  }
718
- return Object.entries(errorsByPath).map(([path18, pathErrors]) => {
867
+ return Object.entries(errorsByPath).map(([path24, pathErrors]) => {
719
868
  let error2 = [...pathErrors].sort(
720
869
  (a, b) => getPriority(a.keyword) - getPriority(b.keyword)
721
870
  )[0], formatter = errorMessages[error2.keyword], message = formatter ? formatter(error2.params) : error2.message;
722
- return ` - ${path18}: ${message}`;
871
+ return ` - ${path24}: ${message}`;
723
872
  }).join(`
724
873
  `);
725
874
  };
@@ -764,7 +913,8 @@ var manifest_schema_default, init_manifest_schema = __esm({
764
913
  items: {
765
914
  type: "string",
766
915
  enum: [
767
- "tracker"
916
+ "tracker",
917
+ "messenger"
768
918
  ]
769
919
  },
770
920
  minItems: 1,
@@ -992,7 +1142,12 @@ var manifest_schema_default, init_manifest_schema = __esm({
992
1142
  items: {
993
1143
  type: "string",
994
1144
  enum: [
995
- "clipboard-write"
1145
+ "clipboard-write",
1146
+ "microphone",
1147
+ "camera",
1148
+ "geolocation",
1149
+ "web-share",
1150
+ "allow-downloads"
996
1151
  ]
997
1152
  },
998
1153
  uniqueItems: !0
@@ -1050,6 +1205,30 @@ var manifest_schema_default, init_manifest_schema = __esm({
1050
1205
  $ref: "#/definitions/SlotConfig"
1051
1206
  }
1052
1207
  },
1208
+ "issue.editor.action": {
1209
+ type: "array",
1210
+ description: "Issue Editor Action slot configurations",
1211
+ minItems: 1,
1212
+ items: {
1213
+ $ref: "#/definitions/SlotConfig"
1214
+ }
1215
+ },
1216
+ "queue.action": {
1217
+ type: "array",
1218
+ description: "Queue Action slot configurations",
1219
+ minItems: 1,
1220
+ items: {
1221
+ $ref: "#/definitions/SlotConfig"
1222
+ }
1223
+ },
1224
+ "queue.tab": {
1225
+ type: "array",
1226
+ description: "Queue Tab slot configurations",
1227
+ minItems: 1,
1228
+ items: {
1229
+ $ref: "#/definitions/SlotConfig"
1230
+ }
1231
+ },
1053
1232
  navigation: {
1054
1233
  type: "array",
1055
1234
  description: "Navigation slot configurations",
@@ -1098,6 +1277,14 @@ var manifest_schema_default, init_manifest_schema = __esm({
1098
1277
  $ref: "#/definitions/SlotConfig"
1099
1278
  }
1100
1279
  },
1280
+ "project.editor.action": {
1281
+ type: "array",
1282
+ description: "Project Editor Action slot configurations",
1283
+ minItems: 1,
1284
+ items: {
1285
+ $ref: "#/definitions/SlotConfig"
1286
+ }
1287
+ },
1101
1288
  "portfolio.action": {
1102
1289
  type: "array",
1103
1290
  description: "Portfolio Action slot configurations",
@@ -1122,6 +1309,14 @@ var manifest_schema_default, init_manifest_schema = __esm({
1122
1309
  $ref: "#/definitions/SlotConfig"
1123
1310
  }
1124
1311
  },
1312
+ "portfolio.editor.action": {
1313
+ type: "array",
1314
+ description: "Portfolio Editor Action slot configurations",
1315
+ minItems: 1,
1316
+ items: {
1317
+ $ref: "#/definitions/SlotConfig"
1318
+ }
1319
+ },
1125
1320
  "goal.action": {
1126
1321
  type: "array",
1127
1322
  description: "Goal Action slot configurations",
@@ -1146,6 +1341,14 @@ var manifest_schema_default, init_manifest_schema = __esm({
1146
1341
  $ref: "#/definitions/SlotConfig"
1147
1342
  }
1148
1343
  },
1344
+ "goal.editor.action": {
1345
+ type: "array",
1346
+ description: "Goal Editor Action slot configurations",
1347
+ minItems: 1,
1348
+ items: {
1349
+ $ref: "#/definitions/SlotConfig"
1350
+ }
1351
+ },
1149
1352
  "attachment.viewer.action": {
1150
1353
  type: "array",
1151
1354
  description: "Attachment Viewer Action slot configurations",
@@ -1172,6 +1375,22 @@ var manifest_schema_default, init_manifest_schema = __esm({
1172
1375
  }
1173
1376
  },
1174
1377
  additionalProperties: !1
1378
+ },
1379
+ messenger: {
1380
+ type: "object",
1381
+ description: "Messenger service slots",
1382
+ minProperties: 1,
1383
+ properties: {
1384
+ "user.card.info": {
1385
+ type: "array",
1386
+ description: "User Card Info slot configurations",
1387
+ minItems: 1,
1388
+ items: {
1389
+ $ref: "#/definitions/SlotConfig"
1390
+ }
1391
+ }
1392
+ },
1393
+ additionalProperties: !1
1175
1394
  }
1176
1395
  },
1177
1396
  additionalProperties: !1
@@ -1362,110 +1581,1269 @@ var manifest_schema_default, init_manifest_schema = __esm({
1362
1581
  }
1363
1582
  });
1364
1583
 
1365
- // src/core/manifest/manifestManager.ts
1366
- var import_fs4, import_promises2, import_ajv, import_ajv_formats, validator, manifestPath, parseManifest, loadRaw, load2, validate, save2, update2, manifestManager, init_manifestManager = __esm({
1367
- "src/core/manifest/manifestManager.ts"() {
1584
+ // src/core/manifest/manifestManager.ts
1585
+ var import_fs3, import_promises, import_ajv, import_ajv_formats, validator, defaultManifestPath, parseManifest, loadRaw, load, validate, save, update, manifestManager, init_manifestManager = __esm({
1586
+ "src/core/manifest/manifestManager.ts"() {
1587
+ "use strict";
1588
+ import_fs3 = require("fs"), import_promises = require("fs/promises"), import_ajv = __toESM(require("ajv")), import_ajv_formats = __toESM(require("ajv-formats"));
1589
+ init_manifestPermissionsSchema2();
1590
+ init_formatValidationErrors();
1591
+ init_manifest_schema();
1592
+ validator = (() => {
1593
+ let schema = {
1594
+ ...manifest_schema_default,
1595
+ properties: {
1596
+ ...manifest_schema_default.properties,
1597
+ permissions: {
1598
+ ...manifest_schema_default.properties.permissions,
1599
+ properties: {
1600
+ ...manifest_schema_default.properties.permissions.properties,
1601
+ ...permissionsSchemaExtensions2
1602
+ }
1603
+ }
1604
+ }
1605
+ }, ajv = new import_ajv.default({ allErrors: !0, strict: !1 });
1606
+ return (0, import_ajv_formats.default)(ajv), ajv.compile(schema);
1607
+ })(), defaultManifestPath = "./manifest.json", parseManifest = (content) => {
1608
+ let manifest;
1609
+ try {
1610
+ manifest = JSON.parse(content);
1611
+ } catch (error2) {
1612
+ throw error2 instanceof SyntaxError ? new Error(`File manifest.json contains invalid JSON: ${error2.message}`) : new Error(`Error reading manifest.json: ${error2.message}`);
1613
+ }
1614
+ return manifest;
1615
+ }, loadRaw = async (manifestPath = defaultManifestPath) => {
1616
+ if (!(0, import_fs3.existsSync)(manifestPath))
1617
+ throw new Error(`File manifest.json not found at path: ${manifestPath}`);
1618
+ try {
1619
+ return await (0, import_promises.readFile)(manifestPath, "utf8");
1620
+ } catch (error2) {
1621
+ throw error2 instanceof Error ? new Error(`Error reading manifest.json: ${error2.message}`) : new Error("Error loading manifest");
1622
+ }
1623
+ }, load = async (manifestPath = defaultManifestPath) => {
1624
+ let manifestContent = await loadRaw(manifestPath);
1625
+ return parseManifest(manifestContent);
1626
+ }, validate = async (manifestPath = defaultManifestPath) => {
1627
+ let manifest = await load(manifestPath);
1628
+ if (!validator(manifest) && validator.errors) {
1629
+ let errorMessages2 = formatValidationErrors(validator.errors);
1630
+ throw new Error(
1631
+ `\u274C Manifest validation failed:
1632
+ ${errorMessages2}
1633
+
1634
+ \u{1F4A1} Ensure all required fields are filled according to the plugin documentation.`
1635
+ );
1636
+ }
1637
+ }, save = async (manifest, manifestPath = defaultManifestPath) => {
1638
+ try {
1639
+ let content = JSON.stringify(manifest, null, 4);
1640
+ await (0, import_promises.writeFile)(manifestPath, content, "utf8");
1641
+ } catch (error2) {
1642
+ throw error2 instanceof Error ? new Error(`Error saving manifest.json: ${error2.message}`) : new Error("Error saving manifest");
1643
+ }
1644
+ }, update = async (updates, manifestPath = defaultManifestPath) => {
1645
+ let updatedManifest = { ...await load(manifestPath), ...updates };
1646
+ return await save(updatedManifest, manifestPath), updatedManifest;
1647
+ }, manifestManager = {
1648
+ load,
1649
+ loadRaw,
1650
+ validate,
1651
+ save,
1652
+ update
1653
+ };
1654
+ }
1655
+ });
1656
+
1657
+ // src/core/doctor/helpers.ts
1658
+ function getErrorMessage(error2) {
1659
+ return error2 instanceof Error ? error2.message : String(error2);
1660
+ }
1661
+ var init_helpers = __esm({
1662
+ "src/core/doctor/helpers.ts"() {
1663
+ "use strict";
1664
+ }
1665
+ });
1666
+
1667
+ // src/core/doctor/manifestChecks.ts
1668
+ function isNonEmptyString(value) {
1669
+ return typeof value == "string" && !!value.trim();
1670
+ }
1671
+ function isSafeRelativePath(value) {
1672
+ if (import_path3.default.isAbsolute(value))
1673
+ return !1;
1674
+ let normalized = import_path3.default.normalize(value);
1675
+ return normalized !== ".." && !normalized.startsWith(`..${import_path3.default.sep}`);
1676
+ }
1677
+ function getManifestEntries(manifest) {
1678
+ let result = [];
1679
+ for (let service of SERVICES) {
1680
+ let serviceSlots = manifest.slots?.[service];
1681
+ if (serviceSlots) {
1682
+ for (let [slot, slotConfigs] of Object.entries(serviceSlots))
1683
+ if (!(!SERVICE_SLOTS.includes(slot) || !Array.isArray(slotConfigs)))
1684
+ for (let slotConfig of slotConfigs) {
1685
+ let slotRecord = slotConfig;
1686
+ result.push({
1687
+ service,
1688
+ slot,
1689
+ entrypoint: slotConfig.entrypoint,
1690
+ title: slotConfig.title,
1691
+ description: slotConfig.description,
1692
+ contextLevel: slotConfig.contextLevel,
1693
+ iconUrl: slotRecord.icon?.url
1694
+ });
1695
+ }
1696
+ }
1697
+ }
1698
+ return result;
1699
+ }
1700
+ function checkLocalizedString(missingValues, name, value) {
1701
+ isNonEmptyString(value?.ru) || missingValues.push(`${name}.ru`), isNonEmptyString(value?.en) || missingValues.push(`${name}.en`);
1702
+ }
1703
+ function checkManifestDetails(report, manifest, policy) {
1704
+ let entries = getManifestEntries(manifest);
1705
+ entries.length > 0 ? addCheck(report, {
1706
+ id: "manifest.entries",
1707
+ title: "Manifest slot entries",
1708
+ message: `Found ${entries.length} plugin slot entry(s).`,
1709
+ data: entries.map((entry) => ({
1710
+ service: entry.service,
1711
+ slot: entry.slot,
1712
+ entrypoint: entry.entrypoint,
1713
+ contextLevel: entry.contextLevel
1714
+ }))
1715
+ }) : addCheck(report, {
1716
+ id: "manifest.entries",
1717
+ title: "Manifest slot entries",
1718
+ status: "fail",
1719
+ message: "Manifest does not define any supported service slot entries.",
1720
+ action: `Add at least one slots.${SERVICES[0]} entry to manifest.json.`
1721
+ });
1722
+ let missingLocalizedStrings = [];
1723
+ checkLocalizedString(missingLocalizedStrings, "name", manifest.name), checkLocalizedString(missingLocalizedStrings, "description", manifest.description);
1724
+ for (let entry of entries)
1725
+ checkLocalizedString(
1726
+ missingLocalizedStrings,
1727
+ `slots.${entry.service}.${entry.slot}.title`,
1728
+ entry.title
1729
+ ), entry.description && checkLocalizedString(
1730
+ missingLocalizedStrings,
1731
+ `slots.${entry.service}.${entry.slot}.description`,
1732
+ entry.description
1733
+ );
1734
+ missingLocalizedStrings.length === 0 ? addCheck(report, {
1735
+ id: "manifest.localized-strings",
1736
+ title: "Localized strings",
1737
+ message: "Manifest localized strings are non-empty."
1738
+ }) : addCheck(report, {
1739
+ id: "manifest.localized-strings",
1740
+ title: "Localized strings",
1741
+ status: "fail",
1742
+ message: `Empty localized value(s): ${missingLocalizedStrings.join(", ")}.`,
1743
+ action: "Fill ru and en values before publishing."
1744
+ });
1745
+ let invalidEntrypoints = entries.map((entry) => entry.entrypoint).filter((entrypoint) => !isSafeRelativePath(entrypoint));
1746
+ return invalidEntrypoints.length > 0 ? addCheck(report, {
1747
+ id: "manifest.entrypoints.valid",
1748
+ title: "Manifest entrypoint paths",
1749
+ status: "fail",
1750
+ message: `Invalid entrypoint path(s): ${invalidEntrypoints.join(", ")}.`,
1751
+ action: "Use relative entrypoint paths inside dist, for example index.html."
1752
+ }) : entries.length > 0 && addCheck(report, {
1753
+ id: "manifest.entrypoints.valid",
1754
+ title: "Manifest entrypoint paths",
1755
+ message: "All manifest entrypoint paths are relative."
1756
+ }), manifest.permissions?.data?.length ? addCheck(report, {
1757
+ id: "manifest.permissions",
1758
+ title: "Manifest permissions",
1759
+ message: `Manifest declares ${manifest.permissions.data.length} data permission(s).`,
1760
+ data: manifest.permissions
1761
+ }) : addCheck(report, {
1762
+ id: "manifest.permissions",
1763
+ title: "Manifest permissions",
1764
+ status: policy.manifestPermissionsStatus,
1765
+ message: "Manifest permissions.data is empty.",
1766
+ action: "Add the data permissions required by the plugin before publishing."
1767
+ }), manifest.support?.length ? addCheck(report, {
1768
+ id: "manifest.support",
1769
+ title: "Support contacts",
1770
+ message: `Manifest declares ${manifest.support.length} support contact(s).`
1771
+ }) : addCheck(report, {
1772
+ id: "manifest.support",
1773
+ title: "Support contacts",
1774
+ status: policy.manifestSupportStatus,
1775
+ message: "Manifest support contacts are missing.",
1776
+ action: "Add at least one support contact to manifest.json before publishing."
1777
+ }), entries;
1778
+ }
1779
+ async function checkManifest(report, manifestPath, policy) {
1780
+ try {
1781
+ await manifestManager.validate(manifestPath);
1782
+ let manifest = await manifestManager.load(manifestPath);
1783
+ return report.manifest = {
1784
+ slug: manifest.slug,
1785
+ version: manifest.version
1786
+ }, addCheck(report, {
1787
+ id: "manifest.valid",
1788
+ title: "Manifest schema",
1789
+ message: "manifest.json is valid."
1790
+ }), {
1791
+ manifest,
1792
+ entries: checkManifestDetails(report, manifest, policy)
1793
+ };
1794
+ } catch (error2) {
1795
+ return addCheck(report, {
1796
+ id: "manifest.valid",
1797
+ title: "Manifest schema",
1798
+ status: "fail",
1799
+ message: getErrorMessage(error2),
1800
+ action: "Fix manifest.json before running build, debug, or submit."
1801
+ }), {
1802
+ entries: []
1803
+ };
1804
+ }
1805
+ }
1806
+ var import_path3, init_manifestChecks = __esm({
1807
+ "src/core/doctor/manifestChecks.ts"() {
1808
+ "use strict";
1809
+ import_path3 = __toESM(require("path"));
1810
+ init_constants();
1811
+ init_manifestManager();
1812
+ init_helpers();
1813
+ init_report();
1814
+ }
1815
+ });
1816
+
1817
+ // src/core/doctor/marketplaceChecks.ts
1818
+ function getMissingOrInvalidStatus(requiredPath, policy) {
1819
+ return requiredPath.path === "src" ? "fail" : policy.marketplaceAssetsStatus;
1820
+ }
1821
+ function checkMarketplaceAssets(report, projectRoot, policy) {
1822
+ for (let requiredPath of REQUIRED_PATHS) {
1823
+ let fullPath = import_path4.default.join(projectRoot, requiredPath.path), status = getMissingOrInvalidStatus(requiredPath, policy);
1824
+ if (!import_fs4.default.existsSync(fullPath)) {
1825
+ addCheck(report, {
1826
+ id: `marketplace.${requiredPath.path}`,
1827
+ title: requiredPath.title,
1828
+ status,
1829
+ message: `${requiredPath.path} is missing.`,
1830
+ action: `Add ${requiredPath.path} before publishing.`
1831
+ });
1832
+ continue;
1833
+ }
1834
+ let stat = import_fs4.default.statSync(fullPath), validKind = requiredPath.kind === "directory" ? stat.isDirectory() : stat.isFile();
1835
+ addCheck(report, {
1836
+ id: `marketplace.${requiredPath.path}`,
1837
+ title: requiredPath.title,
1838
+ status: validKind ? "pass" : status,
1839
+ message: validKind ? `Found ${requiredPath.path}.` : `${requiredPath.path} exists but is not a ${requiredPath.kind}.`,
1840
+ action: validKind ? void 0 : `Replace ${requiredPath.path} with a ${requiredPath.kind}.`
1841
+ });
1842
+ }
1843
+ }
1844
+ var import_fs4, import_path4, REQUIRED_PATHS, init_marketplaceChecks = __esm({
1845
+ "src/core/doctor/marketplaceChecks.ts"() {
1846
+ "use strict";
1847
+ import_fs4 = __toESM(require("fs")), import_path4 = __toESM(require("path"));
1848
+ init_report();
1849
+ REQUIRED_PATHS = [
1850
+ { path: "src", title: "Source directory", kind: "directory" },
1851
+ { path: "marketplace", title: "Marketplace directory", kind: "directory" },
1852
+ { path: "marketplace/index.md", title: "Marketplace description", kind: "file" },
1853
+ { path: "marketplace/header-image.jpg", title: "Marketplace header image", kind: "file" },
1854
+ { path: "public/logo.svg", title: "Plugin logo", kind: "file" }
1855
+ ];
1856
+ }
1857
+ });
1858
+
1859
+ // src/core/doctor/nodeChecks.ts
1860
+ function checkNodeVersion(report) {
1861
+ let version = process.versions.node, major = Number(version.split(".")[0]);
1862
+ if (Number.isInteger(major) && major >= REQUIRED_NODE_MAJOR) {
1863
+ addCheck(report, {
1864
+ id: "node.version",
1865
+ title: "Node.js version",
1866
+ message: `Node.js ${version} satisfies >=${REQUIRED_NODE_MAJOR}.`,
1867
+ data: {
1868
+ version,
1869
+ requiredMajor: REQUIRED_NODE_MAJOR
1870
+ }
1871
+ });
1872
+ return;
1873
+ }
1874
+ addCheck(report, {
1875
+ id: "node.version",
1876
+ title: "Node.js version",
1877
+ status: "fail",
1878
+ message: `Node.js ${version} does not satisfy >=${REQUIRED_NODE_MAJOR}.`,
1879
+ action: `Switch to Node.js ${REQUIRED_NODE_MAJOR} or newer.`,
1880
+ data: {
1881
+ version,
1882
+ requiredMajor: REQUIRED_NODE_MAJOR
1883
+ }
1884
+ });
1885
+ }
1886
+ var REQUIRED_NODE_MAJOR, init_nodeChecks = __esm({
1887
+ "src/core/doctor/nodeChecks.ts"() {
1888
+ "use strict";
1889
+ init_report();
1890
+ REQUIRED_NODE_MAJOR = 22;
1891
+ }
1892
+ });
1893
+
1894
+ // src/utils/packageManager.ts
1895
+ function defaultCommandExists(command) {
1896
+ if (!/^[a-zA-Z0-9_-]+$/.test(command))
1897
+ return !1;
1898
+ let result = (0, import_child_process.spawnSync)("sh", ["-c", `command -v ${command}`], {
1899
+ stdio: "ignore"
1900
+ });
1901
+ return !result.error && result.status === 0;
1902
+ }
1903
+ function detectFromPackageJson(projectRoot) {
1904
+ let packageJsonPath = import_path5.default.join(projectRoot, "package.json");
1905
+ if (import_fs5.default.existsSync(packageJsonPath))
1906
+ try {
1907
+ let raw = import_fs5.default.readFileSync(packageJsonPath, "utf8"), packageManager = JSON.parse(raw).packageManager;
1908
+ if (typeof packageManager != "string")
1909
+ return;
1910
+ if (packageManager.startsWith("pnpm@"))
1911
+ return "pnpm";
1912
+ if (packageManager.startsWith("npm@"))
1913
+ return "npm";
1914
+ } catch {
1915
+ return;
1916
+ }
1917
+ }
1918
+ function detectPackageManager(projectRoot = process.cwd()) {
1919
+ return import_fs5.default.existsSync(import_path5.default.join(projectRoot, "pnpm-lock.yaml")) ? "pnpm" : detectFromPackageJson(projectRoot) || "npm";
1920
+ }
1921
+ function resolvePackageManagerExecutable(packageManager, options = {}) {
1922
+ let commandExists = options.commandExists || defaultCommandExists;
1923
+ if (commandExists(packageManager))
1924
+ return {
1925
+ command: packageManager,
1926
+ argsPrefix: []
1927
+ };
1928
+ if (packageManager !== "npm" && commandExists("corepack"))
1929
+ return {
1930
+ command: "corepack",
1931
+ argsPrefix: [packageManager]
1932
+ };
1933
+ throw packageManager === "npm" ? new Error(
1934
+ "npm is not available in PATH. Install Node.js and npm, then rerun this command."
1935
+ ) : new Error(
1936
+ `${packageManager} is not available in PATH, and Corepack is not available either. Install Node.js >= 22 with Corepack, or run npm install -g corepack@latest && corepack enable once, then rerun this command.`
1937
+ );
1938
+ }
1939
+ function truncateOutput(value) {
1940
+ let normalized = value.trim();
1941
+ return normalized.length <= MAX_RUNTIME_OUTPUT_LENGTH ? normalized : `${normalized.slice(0, MAX_RUNTIME_OUTPUT_LENGTH)}...`;
1942
+ }
1943
+ function getRuntimeOutput(result) {
1944
+ return truncateOutput(
1945
+ [result.stdout?.toString(), result.stderr?.toString()].filter(Boolean).join(`
1946
+ `)
1947
+ );
1948
+ }
1949
+ function isCorepackKeyIdError(output) {
1950
+ return /Cannot find matching keyid/i.test(output);
1951
+ }
1952
+ function getPackageManagerRuntimeAction(output, packageManager) {
1953
+ return isCorepackKeyIdError(output) ? `Corepack cannot verify the pinned package manager signature. Update Corepack from the same registry used for global CLI installs: npm install -g corepack@latest && corepack enable. Then rerun: ${packageManager === "npm" ? "npm install" : `corepack ${packageManager} install`}. Do not use COREPACK_INTEGRITY_KEYS=0 because it disables signature checks.` : packageManager === "npm" ? "Fix the npm runtime, then rerun doctor. For freshly generated plugins, install Node.js >= 22 and run npm install from the plugin directory." : `Fix the ${packageManager} runtime, then rerun doctor. For Corepack-managed package managers, try: npm install -g corepack@latest && corepack enable.`;
1954
+ }
1955
+ function runPackageManagerRuntimeCheck(projectRoot, packageManager, executable) {
1956
+ let args = [...executable.argsPrefix, "--version"], commandLabel = [executable.command, ...args].join(" "), result = (0, import_child_process.spawnSync)(executable.command, args, {
1957
+ cwd: projectRoot,
1958
+ encoding: "utf8",
1959
+ timeout: PACKAGE_MANAGER_RUNTIME_TIMEOUT_MS
1960
+ }), output = getRuntimeOutput(result);
1961
+ if (!result.error && result.status === 0)
1962
+ return {
1963
+ ok: !0,
1964
+ packageManager,
1965
+ command: executable.command,
1966
+ args,
1967
+ commandLabel,
1968
+ message: `${commandLabel} returned ${output || "success"}.`,
1969
+ version: output || void 0,
1970
+ status: result.status,
1971
+ signal: result.signal,
1972
+ output: output || null
1973
+ };
1974
+ let message = result.error ? result.error.message : output || `${commandLabel} exited with code ${result.status}.`;
1975
+ return {
1976
+ ok: !1,
1977
+ packageManager,
1978
+ command: executable.command,
1979
+ args,
1980
+ commandLabel,
1981
+ message,
1982
+ action: getPackageManagerRuntimeAction(output || message, packageManager),
1983
+ status: result.status,
1984
+ signal: result.signal,
1985
+ output: output || null
1986
+ };
1987
+ }
1988
+ var import_child_process, import_fs5, import_path5, PACKAGE_MANAGER_RUNTIME_TIMEOUT_MS, MAX_RUNTIME_OUTPUT_LENGTH, PackageManagerRuntimeError, init_packageManager = __esm({
1989
+ "src/utils/packageManager.ts"() {
1990
+ "use strict";
1991
+ import_child_process = require("child_process"), import_fs5 = __toESM(require("fs")), import_path5 = __toESM(require("path")), PACKAGE_MANAGER_RUNTIME_TIMEOUT_MS = 15e3, MAX_RUNTIME_OUTPUT_LENGTH = 1e3, PackageManagerRuntimeError = class extends Error {
1992
+ constructor(check) {
1993
+ super(check.message), this.name = "PackageManagerRuntimeError", this.action = check.action, this.check = check;
1994
+ }
1995
+ };
1996
+ }
1997
+ });
1998
+
1999
+ // src/core/doctor/packageChecks.ts
2000
+ function readPackageJson(projectRoot) {
2001
+ let packageJsonPath = import_path6.default.join(projectRoot, "package.json");
2002
+ if (!import_fs6.default.existsSync(packageJsonPath))
2003
+ return {
2004
+ path: packageJsonPath,
2005
+ error: "package.json not found"
2006
+ };
2007
+ try {
2008
+ let raw = import_fs6.default.readFileSync(packageJsonPath, "utf8");
2009
+ return {
2010
+ path: packageJsonPath,
2011
+ packageJson: JSON.parse(raw)
2012
+ };
2013
+ } catch (error2) {
2014
+ return {
2015
+ path: packageJsonPath,
2016
+ error: getErrorMessage(error2)
2017
+ };
2018
+ }
2019
+ }
2020
+ function getScript(packageJson, name) {
2021
+ if (typeof packageJson.scripts != "object" || packageJson.scripts === null)
2022
+ return;
2023
+ let value = packageJson.scripts[name];
2024
+ return typeof value == "string" && value.trim() ? value : void 0;
2025
+ }
2026
+ function getDependencyVersion(packageJson, name) {
2027
+ let dependencySources = [packageJson.dependencies, packageJson.devDependencies];
2028
+ for (let source of dependencySources) {
2029
+ if (typeof source != "object" || source === null)
2030
+ continue;
2031
+ let value = source[name];
2032
+ if (typeof value == "string" && value.trim())
2033
+ return value;
2034
+ }
2035
+ }
2036
+ function addPackageManagerRuntimeCheck(report, runtimeCheck) {
2037
+ if (runtimeCheck.ok) {
2038
+ addCheck(report, {
2039
+ id: "package-manager.runtime",
2040
+ title: "Package manager runtime",
2041
+ message: runtimeCheck.message,
2042
+ data: {
2043
+ packageManager: runtimeCheck.packageManager,
2044
+ command: runtimeCheck.command,
2045
+ args: runtimeCheck.args,
2046
+ version: runtimeCheck.version || null
2047
+ }
2048
+ });
2049
+ return;
2050
+ }
2051
+ addCheck(report, {
2052
+ id: "package-manager.runtime",
2053
+ title: "Package manager runtime",
2054
+ status: "fail",
2055
+ message: runtimeCheck.message,
2056
+ action: runtimeCheck.action,
2057
+ data: {
2058
+ packageManager: runtimeCheck.packageManager,
2059
+ command: runtimeCheck.command,
2060
+ args: runtimeCheck.args,
2061
+ status: runtimeCheck.status,
2062
+ signal: runtimeCheck.signal,
2063
+ output: runtimeCheck.output
2064
+ }
2065
+ });
2066
+ }
2067
+ function getPackageManagerInstallAction(packageManager) {
2068
+ return packageManager === "npm" ? "Install Node.js >= 22 with npm, then rerun npm install." : `Install and enable Corepack once: npm install -g corepack@latest && corepack enable. Then rerun corepack ${packageManager} install.`;
2069
+ }
2070
+ function checkScript(report, packageJson, script, required) {
2071
+ let value = getScript(packageJson, script);
2072
+ if (value) {
2073
+ addCheck(report, {
2074
+ id: `package-json.script.${script}`,
2075
+ title: `${script} script`,
2076
+ message: `${script} script is "${value}".`
2077
+ });
2078
+ return;
2079
+ }
2080
+ addCheck(report, {
2081
+ id: `package-json.script.${script}`,
2082
+ title: `${script} script`,
2083
+ status: required ? "fail" : "warn",
2084
+ message: `Missing package.json scripts.${script}.`,
2085
+ action: required ? `Add scripts.${script}; CLI commands expect it.` : `Add scripts.${script} if this plugin should support this check.`
2086
+ });
2087
+ }
2088
+ function checkPluginSdkDependency(report, packageJson) {
2089
+ let detectedPackages = COMMON_SDK_PACKAGES.filter(
2090
+ (packageName) => getDependencyVersion(packageJson, packageName)
2091
+ ), detectedGenericPackages = GENERIC_SDK_PACKAGES.filter(
2092
+ (packageName) => getDependencyVersion(packageJson, packageName)
2093
+ ), missingGenericPackages = GENERIC_SDK_PACKAGES.filter(
2094
+ (packageName) => !getDependencyVersion(packageJson, packageName)
2095
+ );
2096
+ if (detectedPackages.length > 0) {
2097
+ addCheck(report, {
2098
+ id: "package-json.sdk-dependency",
2099
+ title: "Plugin SDK dependency",
2100
+ message: `Uses common plugin SDK package(s): ${detectedPackages.join(", ")}.`,
2101
+ data: detectedPackages
2102
+ }), detectedGenericPackages.length > 0 && missingGenericPackages.length > 0 && addCheck(report, {
2103
+ id: "package-json.sdk-generic-pair",
2104
+ title: "Generic SDK dependency pair",
2105
+ status: "warn",
2106
+ message: `Generic SDK dependency set is incomplete. Missing: ${missingGenericPackages.join(", ")}.`,
2107
+ action: "Generated generic React templates depend on both @weavix/sdk-core and @weavix/sdk-react.",
2108
+ data: {
2109
+ detected: detectedGenericPackages,
2110
+ missing: missingGenericPackages
2111
+ }
2112
+ });
2113
+ return;
2114
+ }
2115
+ addCheck(report, {
2116
+ id: "package-json.sdk-dependency",
2117
+ title: "Plugin SDK dependency",
2118
+ status: "warn",
2119
+ message: "No common plugin SDK package was found in dependencies.",
2120
+ action: "Add @weavix/sdk-core + @weavix/sdk-react for generic plugins, or @weavix/tracker-plugin-sdk-react for Tracker plugins."
2121
+ });
2122
+ }
2123
+ function checkPackageJson(report, projectRoot) {
2124
+ let result = readPackageJson(projectRoot);
2125
+ if (!result.packageJson) {
2126
+ addCheck(report, {
2127
+ id: "package-json.valid",
2128
+ title: "package.json",
2129
+ status: "fail",
2130
+ message: result.error || "package.json cannot be read.",
2131
+ action: `Create a valid package.json at ${result.path}.`
2132
+ });
2133
+ return;
2134
+ }
2135
+ return addCheck(report, {
2136
+ id: "package-json.valid",
2137
+ title: "package.json",
2138
+ message: `Found valid package.json at ${result.path}.`
2139
+ }), typeof result.packageJson.packageManager == "string" ? addCheck(report, {
2140
+ id: "package-json.package-manager",
2141
+ title: "Pinned package manager",
2142
+ message: `packageManager is ${result.packageJson.packageManager}.`
2143
+ }) : addCheck(report, {
2144
+ id: "package-json.package-manager",
2145
+ title: "Pinned package manager",
2146
+ status: "warn",
2147
+ message: "packageManager is missing. CLI will fall back to lockfiles or npm.",
2148
+ action: 'Add packageManager, for example "npm@11.6.4".'
2149
+ }), checkScript(report, result.packageJson, "build", !0), checkScript(report, result.packageJson, "lint", !0), checkScript(report, result.packageJson, "dev", !1), checkScript(report, result.packageJson, "typecheck", !1), checkScript(report, result.packageJson, "test", !1), checkPluginSdkDependency(report, result.packageJson), result.packageJson;
2150
+ }
2151
+ function checkPackageManager(report, projectRoot) {
2152
+ let projectPackageManager = detectPackageManager(projectRoot);
2153
+ report.packageManager = projectPackageManager, projectPackageManager !== CLI_PACKAGE_MANAGER && addCheck(report, {
2154
+ id: "package-manager.cli-compat",
2155
+ title: "CLI package manager compatibility",
2156
+ status: "warn",
2157
+ message: `Detected ${projectPackageManager}, but existing CLI build/debug/submit commands run ${CLI_PACKAGE_MANAGER}.`,
2158
+ action: "Use npm for generated plugins until CLI command execution is made package-manager aware.",
2159
+ data: {
2160
+ packageManager: projectPackageManager,
2161
+ cliPackageManager: CLI_PACKAGE_MANAGER
2162
+ }
2163
+ });
2164
+ try {
2165
+ let executable = resolvePackageManagerExecutable(CLI_PACKAGE_MANAGER);
2166
+ addCheck(report, {
2167
+ id: "package-manager.executable",
2168
+ title: "CLI package manager executable",
2169
+ message: `CLI commands run ${[executable.command, ...executable.argsPrefix].join(
2170
+ " "
2171
+ )}.`,
2172
+ data: {
2173
+ packageManager: projectPackageManager,
2174
+ cliPackageManager: CLI_PACKAGE_MANAGER,
2175
+ executable
2176
+ }
2177
+ }), addPackageManagerRuntimeCheck(
2178
+ report,
2179
+ runPackageManagerRuntimeCheck(projectRoot, CLI_PACKAGE_MANAGER, executable)
2180
+ );
2181
+ } catch (error2) {
2182
+ addCheck(report, {
2183
+ id: "package-manager.executable",
2184
+ title: "CLI package manager executable",
2185
+ status: "fail",
2186
+ message: getErrorMessage(error2),
2187
+ action: getPackageManagerInstallAction(CLI_PACKAGE_MANAGER),
2188
+ data: {
2189
+ packageManager: projectPackageManager,
2190
+ cliPackageManager: CLI_PACKAGE_MANAGER
2191
+ }
2192
+ });
2193
+ }
2194
+ }
2195
+ var import_fs6, import_path6, CLI_PACKAGE_MANAGER, COMMON_SDK_PACKAGES, GENERIC_SDK_PACKAGES, init_packageChecks = __esm({
2196
+ "src/core/doctor/packageChecks.ts"() {
2197
+ "use strict";
2198
+ import_fs6 = __toESM(require("fs")), import_path6 = __toESM(require("path"));
2199
+ init_packageManager();
2200
+ init_helpers();
2201
+ init_report();
2202
+ CLI_PACKAGE_MANAGER = "npm", COMMON_SDK_PACKAGES = [
2203
+ "@weavix/sdk-core",
2204
+ "@weavix/sdk-react",
2205
+ "@weavix/tracker-plugin-sdk",
2206
+ "@weavix/tracker-plugin-sdk-react",
2207
+ "@yandex-weavix/tracker-plugin-sdk-core",
2208
+ "@yandex-weavix/tracker-plugin-sdk-react"
2209
+ ], GENERIC_SDK_PACKAGES = ["@weavix/sdk-core", "@weavix/sdk-react"];
2210
+ }
2211
+ });
2212
+
2213
+ // src/utils/project.ts
2214
+ function resolveProjectRoot(startDir = process.cwd()) {
2215
+ let current = import_path7.default.resolve(startDir);
2216
+ for (; ; ) {
2217
+ if (import_fs7.default.existsSync(import_path7.default.join(current, MANIFEST_FILE)))
2218
+ return current;
2219
+ let parent = import_path7.default.dirname(current);
2220
+ if (parent === current)
2221
+ throw new Error(
2222
+ `Could not find ${MANIFEST_FILE}. Run this command inside a plugin project.`
2223
+ );
2224
+ current = parent;
2225
+ }
2226
+ }
2227
+ function getManifestPath(projectRoot = process.cwd()) {
2228
+ return import_path7.default.join(resolveProjectRoot(projectRoot), MANIFEST_FILE);
2229
+ }
2230
+ var import_fs7, import_path7, MANIFEST_FILE, init_project = __esm({
2231
+ "src/utils/project.ts"() {
2232
+ "use strict";
2233
+ import_fs7 = __toESM(require("fs")), import_path7 = __toESM(require("path")), MANIFEST_FILE = "manifest.json";
2234
+ }
2235
+ });
2236
+
2237
+ // src/core/doctor/projectChecks.ts
2238
+ function checkProjectRoot(report) {
2239
+ try {
2240
+ let projectRoot = resolveProjectRoot();
2241
+ return report.projectRoot = projectRoot, report.manifestPath = getManifestPath(projectRoot), addCheck(report, {
2242
+ id: "project-root.resolved",
2243
+ title: "Project root",
2244
+ message: `Found plugin project root at ${projectRoot}.`
2245
+ }), projectRoot;
2246
+ } catch (error2) {
2247
+ addCheck(report, {
2248
+ id: "project-root.resolved",
2249
+ title: "Project root",
2250
+ status: "fail",
2251
+ message: getErrorMessage(error2),
2252
+ action: "Run doctor inside a generated plugin project."
2253
+ });
2254
+ return;
2255
+ }
2256
+ }
2257
+ var init_projectChecks = __esm({
2258
+ "src/core/doctor/projectChecks.ts"() {
2259
+ "use strict";
2260
+ init_project();
2261
+ init_helpers();
2262
+ init_report();
2263
+ }
2264
+ });
2265
+
2266
+ // src/core/doctor/checks.ts
2267
+ async function runDoctorChecks(options) {
2268
+ let report = createDoctorReport(), policy = createDoctorPolicy(options);
2269
+ report.mode = policy.mode, checkNodeVersion(report);
2270
+ let projectRoot = checkProjectRoot(report);
2271
+ if (!projectRoot)
2272
+ return await checkDistribution2(report, void 0, options, policy), report;
2273
+ let { manifest, entries } = await checkManifest(report, report.manifestPath, policy);
2274
+ return checkPackageJson(report, projectRoot) && checkPackageManager(report, projectRoot), manifest && await checkDist(report, projectRoot, entries, policy), checkMarketplaceAssets(report, projectRoot, policy), await checkDistribution2(report, projectRoot, options, policy), report;
2275
+ }
2276
+ var init_checks = __esm({
2277
+ "src/core/doctor/checks.ts"() {
2278
+ "use strict";
2279
+ init_doctorChecks2();
2280
+ init_distChecks();
2281
+ init_manifestChecks();
2282
+ init_marketplaceChecks();
2283
+ init_nodeChecks();
2284
+ init_packageChecks();
2285
+ init_policy();
2286
+ init_projectChecks();
2287
+ init_report();
2288
+ }
2289
+ });
2290
+
2291
+ // src/commands/doctor/index.ts
2292
+ async function doctor(options = {}) {
2293
+ let report = await runDoctorChecks(options);
2294
+ await finishDoctor(report, options);
2295
+ }
2296
+ var init_doctor = __esm({
2297
+ "src/commands/doctor/index.ts"() {
2298
+ "use strict";
2299
+ init_checks();
2300
+ init_report();
2301
+ }
2302
+ });
2303
+
2304
+ // src/commands/submit/options.ts
2305
+ var import_commander, skipChecksOption, init_options = __esm({
2306
+ "src/commands/submit/options.ts"() {
2307
+ "use strict";
2308
+ import_commander = require("commander"), skipChecksOption = new import_commander.Option(
2309
+ "--skip-checks",
2310
+ "skip pre-submit validation (manifest, assets, lint, typecheck, tests, audit)"
2311
+ );
2312
+ }
2313
+ });
2314
+
2315
+ // src/utils/verbose.ts
2316
+ function setVerboseEnabled(value) {
2317
+ verboseEnabled = value;
2318
+ }
2319
+ function isVerboseEnabled() {
2320
+ return verboseEnabled;
2321
+ }
2322
+ function writeVerboseArtifact(relativePath, content) {
2323
+ let targetPath = import_path8.default.resolve(".yaweavix-debug", relativePath);
2324
+ return import_fs8.default.mkdirSync(import_path8.default.dirname(targetPath), { recursive: !0 }), import_fs8.default.writeFileSync(targetPath, content), targetPath;
2325
+ }
2326
+ var import_fs8, import_path8, verboseEnabled, init_verbose = __esm({
2327
+ "src/utils/verbose.ts"() {
2328
+ "use strict";
2329
+ import_fs8 = __toESM(require("fs")), import_path8 = __toESM(require("path")), verboseEnabled = !1;
2330
+ }
2331
+ });
2332
+
2333
+ // src/utils/logger.ts
2334
+ function success(message) {
2335
+ console.info(import_picocolors.default.green(`\u2705 ${message}`)), newLine();
2336
+ }
2337
+ function error(messageOrErr, err) {
2338
+ let message = messageOrErr instanceof Error ? messageOrErr.message : messageOrErr;
2339
+ console.error(import_picocolors.default.red(`\u274C ${message}`)), err instanceof Error && console.error(import_picocolors.default.red(err.message)), newLine();
2340
+ }
2341
+ function warning(message) {
2342
+ console.warn(import_picocolors.default.yellow(`\u26A0\uFE0F ${message}`)), newLine();
2343
+ }
2344
+ function info(message) {
2345
+ console.info(message), newLine();
2346
+ }
2347
+ function verbose(message) {
2348
+ isVerboseEnabled() && (console.info(import_picocolors.default.dim(message)), newLine());
2349
+ }
2350
+ function suggest(command) {
2351
+ console.info(`Run: ${command}`), newLine();
2352
+ }
2353
+ function newLine(count = 1) {
2354
+ console.info(`
2355
+ `.repeat(count - 1));
2356
+ }
2357
+ function separator(char = "\u2500", length = 60) {
2358
+ console.info(import_picocolors.default.dim(char.repeat(length))), newLine();
2359
+ }
2360
+ function commands(title, data) {
2361
+ newLine(), title && (console.info(import_picocolors.default.bold(import_picocolors.default.cyan(`${title}:`))), newLine()), data.forEach((cmd) => {
2362
+ console.info(import_picocolors.default.dim(" $ ") + import_picocolors.default.white(cmd));
2363
+ }), newLine();
2364
+ }
2365
+ var import_picocolors, logger, logger_default, init_logger = __esm({
2366
+ "src/utils/logger.ts"() {
2367
+ "use strict";
2368
+ import_picocolors = __toESM(require("picocolors"));
2369
+ init_verbose();
2370
+ logger = {
2371
+ success,
2372
+ error,
2373
+ warning,
2374
+ info,
2375
+ verbose,
2376
+ suggest,
2377
+ newLine,
2378
+ separator,
2379
+ commands
2380
+ }, logger_default = logger;
2381
+ }
2382
+ });
2383
+
2384
+ // src/core/cliConfig/registerCommand.ts
2385
+ async function promptString(message, current) {
2386
+ return (await (0, import_prompts.input)({
2387
+ message: current ? `${message} (current: ${current})` : `${message} (optional)`,
2388
+ default: current,
2389
+ required: !1
2390
+ }))?.trim() || void 0;
2391
+ }
2392
+ async function runConfigSet(cliName) {
2393
+ let existing = readConfig() ?? {};
2394
+ logger_default.info(
2395
+ "Configure CLI overrides. Empty input clears the value (and falls back to defaults where applicable)."
2396
+ );
2397
+ 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(
2398
+ "Production bucket (static)",
2399
+ existing.buckets?.production?.static
2400
+ ), productionConfig = await promptString(
2401
+ "Production bucket (config)",
2402
+ existing.buckets?.production?.config
2403
+ ), pluginDownloadProduction = await promptString(
2404
+ "Plugin download base URL",
2405
+ existing.pluginDownloadBase?.production
2406
+ ), platformBaseUrl = await promptString(
2407
+ "Platform API base URL",
2408
+ existing.api?.platformBaseUrl
2409
+ ), oauthUrl = await promptString("OAuth token URL", existing.auth?.oauthUrl);
2410
+ writeConfig({
2411
+ s3: { endpoint: s3Endpoint, region: s3Region },
2412
+ mds: { endpoint: mdsEndpoint },
2413
+ buckets: {
2414
+ production: { static: productionStatic, config: productionConfig }
2415
+ },
2416
+ pluginDownloadBase: { production: pluginDownloadProduction },
2417
+ api: { platformBaseUrl },
2418
+ auth: { oauthUrl }
2419
+ }), logger_default.success(`Configuration saved \u2192 ${getConfigPath()}`), logger_default.info(`Inspect with "${cliName} config show" or revert with "${cliName} config clear".`);
2420
+ }
2421
+ function runConfigShow(cliName) {
2422
+ let cfg = readConfig();
2423
+ if (!cfg) {
2424
+ logger_default.info(
2425
+ `No configuration found at ${getConfigPath()}. Run "${cliName} config set" to create one.`
2426
+ );
2427
+ return;
2428
+ }
2429
+ logger_default.info(`Configuration at ${getConfigPath()}:`), logger_default.info(JSON.stringify(cfg, null, 2));
2430
+ }
2431
+ function runConfigClear() {
2432
+ clearConfig(), logger_default.success(`Configuration removed (${getConfigPath()})`);
2433
+ }
2434
+ function registerConfigCommand(program, cliName) {
2435
+ let config = program.command("config").description("manage CLI configuration");
2436
+ 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);
2437
+ }
2438
+ var import_prompts, init_registerCommand = __esm({
2439
+ "src/core/cliConfig/registerCommand.ts"() {
2440
+ "use strict";
2441
+ import_prompts = require("@inquirer/prompts");
2442
+ init_logger();
2443
+ init_manager();
2444
+ }
2445
+ });
2446
+
2447
+ // src/utils/withErrorHandling.ts
2448
+ function withErrorHandling(fn) {
2449
+ return async (...args) => {
2450
+ try {
2451
+ await fn(...args);
2452
+ } catch (error2) {
2453
+ error2 instanceof Error && error2.name === "ExitPromptError" && process.exit(0), logger_default.error(error2), printErrorHints(error2), process.exit(1);
2454
+ }
2455
+ };
2456
+ }
2457
+ function getErrorMessage2(error2) {
2458
+ return error2 instanceof Error ? error2.message : String(error2);
2459
+ }
2460
+ function printErrorHints(error2) {
2461
+ if (error2 instanceof PackageManagerRuntimeError) {
2462
+ error2.action && logger_default.info(`Action: ${error2.action}`), logger_default.info(`Run ${CLI_NAME2} doctor from the plugin directory for full local diagnostics.`);
2463
+ return;
2464
+ }
2465
+ let message = getErrorMessage2(error2);
2466
+ if (isCorepackKeyIdError(message)) {
2467
+ logger_default.info(`Action: ${getPackageManagerRuntimeAction(message, "pnpm")}`);
2468
+ return;
2469
+ }
2470
+ /\b(manifest\.json|manifest validation|package manager|corepack|pnpm|npm|build|dist)\b/i.test(
2471
+ message
2472
+ ) && logger_default.info(`Run ${CLI_NAME2} doctor from the plugin directory for local diagnostics.`);
2473
+ }
2474
+ var init_withErrorHandling = __esm({
2475
+ "src/utils/withErrorHandling.ts"() {
2476
+ "use strict";
2477
+ init_meta2();
2478
+ init_logger();
2479
+ init_packageManager();
2480
+ }
2481
+ });
2482
+
2483
+ // src/core/pluginState/pluginStateManager.ts
2484
+ var import_fs9, import_promises2, STATE_FILE, load2, save2, update2, pluginStateManager, init_pluginStateManager = __esm({
2485
+ "src/core/pluginState/pluginStateManager.ts"() {
2486
+ "use strict";
2487
+ import_fs9 = require("fs"), import_promises2 = require("fs/promises"), STATE_FILE = ".tracker-plugin", load2 = async () => {
2488
+ if (!(0, import_fs9.existsSync)(STATE_FILE))
2489
+ return {};
2490
+ try {
2491
+ let content = await (0, import_promises2.readFile)(STATE_FILE, "utf8");
2492
+ return JSON.parse(content);
2493
+ } catch {
2494
+ return {};
2495
+ }
2496
+ }, save2 = async (state) => {
2497
+ try {
2498
+ let content = JSON.stringify(state, null, 4);
2499
+ await (0, import_promises2.writeFile)(STATE_FILE, content, "utf8");
2500
+ } catch (error2) {
2501
+ throw error2 instanceof Error ? new Error(`Error saving ${STATE_FILE}: ${error2.message}`) : new Error(`Error saving ${STATE_FILE}`);
2502
+ }
2503
+ }, update2 = async (updates) => {
2504
+ let updated = { ...await load2(), ...updates };
2505
+ return await save2(updated), updated;
2506
+ }, pluginStateManager = {
2507
+ load: load2,
2508
+ save: save2,
2509
+ update: update2
2510
+ };
2511
+ }
2512
+ });
2513
+
2514
+ // src/api/utils.ts
2515
+ function getIssueStatusLabel(issue) {
2516
+ let { key: statusKey, display: statusDisplay } = issue.status;
2517
+ return statusKey === "closed" && issue.resolution?.display ? issue.resolution.display : statusDisplay ?? statusKey;
2518
+ }
2519
+ function getIssueStatusCategory(issue) {
2520
+ let statusKey = issue.status.key, resolutionKey = issue.resolution?.key;
2521
+ if (statusKey === "closed")
2522
+ return resolutionKey === "agreed" ? "approved" : resolutionKey === "rejected" || resolutionKey === "declined" ? "rejected" : "neutral";
2523
+ switch (statusKey) {
2524
+ case "waitingForApprove":
2525
+ case "inProgress":
2526
+ return "pending";
2527
+ case "resultAcceptance":
2528
+ return "acceptance";
2529
+ case "testing":
2530
+ return "testing";
2531
+ case "need_info":
2532
+ return "need_info";
2533
+ default:
2534
+ return "neutral";
2535
+ }
2536
+ }
2537
+ var init_utils = __esm({
2538
+ "src/api/utils.ts"() {
2539
+ "use strict";
2540
+ }
2541
+ });
2542
+
2543
+ // src/utils/pluginDisplay.ts
2544
+ function showTrackerPluginList(issues) {
2545
+ if (!issues || issues.length === 0) {
2546
+ console.info(import_picocolors2.default.dim(" No plugins found")), logger_default.newLine();
2547
+ return;
2548
+ }
2549
+ printHeader(`\u{1F4CB} Your Plugins \xB7 ${issues.length}`), logger_default.newLine(), issues.forEach((issue) => {
2550
+ let slugMatch = issue.summary.match(/^Plugin:\s*(.+)$/), slug = slugMatch ? import_picocolors2.default.magenta(slugMatch[1].trim()) : import_picocolors2.default.dim(issue.summary), statusBadge2 = getTrackerIssueBadge(issue);
2551
+ console.info(
2552
+ ` ${slug} ${import_picocolors2.default.dim("\xB7")} ${statusBadge2} ${import_picocolors2.default.dim("\xB7")} ${import_picocolors2.default.dim(issue.key)}`
2553
+ ), logger_default.newLine();
2554
+ });
2555
+ }
2556
+ function showTrackerPluginInfo(issue) {
2557
+ printHeader("\u{1F4E6} Plugin"), logger_default.newLine(), printField("Issue key", import_picocolors2.default.cyan(issue.key)), printField("Status", getTrackerIssueBadge(issue)), printField("Summary", import_picocolors2.default.white(issue.summary)), issue.createdAt && printCreated(issue.createdAt), issue.updatedAt && printUpdated(issue.updatedAt);
2558
+ }
2559
+ var import_picocolors2, printHeader, getTrackerIssueBadge, formatDate, printField, printCreated, printUpdated, init_pluginDisplay = __esm({
2560
+ "src/utils/pluginDisplay.ts"() {
2561
+ "use strict";
2562
+ import_picocolors2 = __toESM(require("picocolors"));
2563
+ init_utils();
2564
+ init_logger();
2565
+ printHeader = (title) => {
2566
+ console.info(import_picocolors2.default.bold(import_picocolors2.default.white(title)));
2567
+ }, getTrackerIssueBadge = (issue) => {
2568
+ let label = getIssueStatusLabel(issue);
2569
+ switch (getIssueStatusCategory(issue)) {
2570
+ case "approved":
2571
+ return import_picocolors2.default.black(import_picocolors2.default.bgGreen(` ${label} `));
2572
+ case "rejected":
2573
+ return import_picocolors2.default.white(import_picocolors2.default.bgRed(` ${label} `));
2574
+ case "pending":
2575
+ return import_picocolors2.default.black(import_picocolors2.default.bgYellow(` ${label} `));
2576
+ case "acceptance":
2577
+ return import_picocolors2.default.black(import_picocolors2.default.bgCyan(` ${label} `));
2578
+ case "testing":
2579
+ return import_picocolors2.default.black(import_picocolors2.default.bgMagenta(` ${label} `));
2580
+ case "need_info":
2581
+ return import_picocolors2.default.black(import_picocolors2.default.bgBlue(` ${label} `));
2582
+ default:
2583
+ return import_picocolors2.default.black(import_picocolors2.default.bgWhite(` ${label} `));
2584
+ }
2585
+ }, formatDate = (dateString) => dateString ? new Date(dateString).toLocaleString("ru-RU", {
2586
+ year: "numeric",
2587
+ month: "2-digit",
2588
+ day: "2-digit",
2589
+ hour: "2-digit",
2590
+ minute: "2-digit"
2591
+ }) : "-", printField = (label, value, minWidth = 12) => {
2592
+ console.info(` ${import_picocolors2.default.dim(label.padEnd(minWidth))} ${value}`);
2593
+ }, printCreated = (createdAt) => {
2594
+ printField("Created", import_picocolors2.default.white(formatDate(createdAt)));
2595
+ }, printUpdated = (updatedAt) => {
2596
+ printField("Updated", import_picocolors2.default.white(formatDate(updatedAt)));
2597
+ };
2598
+ }
2599
+ });
2600
+
2601
+ // src/distributions/external/tracker.ts
2602
+ function buildIssueSummary(slug) {
2603
+ return `Plugin: ${slug}`;
2604
+ }
2605
+ function buildIssueDescription(params) {
2606
+ let { pluginId, slug, version, manifestJson } = params;
2607
+ return [
2608
+ `**Plugin UUID:** ${pluginId}`,
2609
+ `**Slug:** ${slug}`,
2610
+ `**Version:** ${version}`,
2611
+ "",
2612
+ "**Manifest:**",
2613
+ "```json",
2614
+ manifestJson,
2615
+ "```"
2616
+ ].join(`
2617
+ `);
2618
+ }
2619
+ async function createPluginIssue(params) {
2620
+ let { slug, pluginId, version, manifestJson } = params, body = {
2621
+ queue: PLUGINMOD_QUEUE,
2622
+ summary: buildIssueSummary(slug),
2623
+ description: buildIssueDescription({ pluginId, slug, version, manifestJson }),
2624
+ tags: ["tracker-plugin"]
2625
+ };
2626
+ return externalTrackerApiRequest("/issues", {
2627
+ method: "POST",
2628
+ body
2629
+ });
2630
+ }
2631
+ async function updatePluginIssue(issueKey, params) {
2632
+ return externalTrackerApiRequest(`/issues/${issueKey}`, {
2633
+ method: "PATCH",
2634
+ body: params
2635
+ });
2636
+ }
2637
+ async function attachFileToIssue(issueKey, fileBuffer, fileName) {
2638
+ let formData = new import_form_data.default();
2639
+ return formData.append("file", fileBuffer, {
2640
+ filename: fileName,
2641
+ contentType: "application/zip"
2642
+ }), externalTrackerApiRequest(`/issues/${issueKey}/attachments`, {
2643
+ method: "POST",
2644
+ formData
2645
+ });
2646
+ }
2647
+ async function getIssueTransitions(issueKey) {
2648
+ return externalTrackerApiRequest(`/issues/${issueKey}/transitions`, {
2649
+ method: "GET"
2650
+ });
2651
+ }
2652
+ async function executeIssueTransition(issueKey, transitionId) {
2653
+ await externalTrackerApiRequest(
2654
+ `/issues/${issueKey}/transitions/${transitionId}/_execute`,
2655
+ {
2656
+ method: "POST",
2657
+ body: {}
2658
+ }
2659
+ );
2660
+ }
2661
+ async function getIssue(issueKey) {
2662
+ return externalTrackerApiRequest(`/issues/${issueKey}`, {
2663
+ method: "GET"
2664
+ });
2665
+ }
2666
+ async function addIssueComment(issueKey, text) {
2667
+ await externalTrackerApiRequest(`/issues/${issueKey}/comments`, {
2668
+ method: "POST",
2669
+ body: { text }
2670
+ });
2671
+ }
2672
+ async function getMyPluginIssues() {
2673
+ return externalTrackerApiRequest("/issues/_search", {
2674
+ method: "POST",
2675
+ body: {
2676
+ filter: {
2677
+ queue: "PLUGINMOD",
2678
+ createdBy: "me()"
2679
+ }
2680
+ }
2681
+ });
2682
+ }
2683
+ var import_form_data, PLUGINMOD_QUEUE, init_tracker = __esm({
2684
+ "src/distributions/external/tracker.ts"() {
2685
+ "use strict";
2686
+ import_form_data = __toESM(require("form-data"));
2687
+ init_trackerApiRequest();
2688
+ PLUGINMOD_QUEUE = "PLUGINMOD";
2689
+ }
2690
+ });
2691
+
2692
+ // src/distributions/external/info.ts
2693
+ async function infoExternal(issueKey) {
2694
+ let targetIssueKey = issueKey;
2695
+ if (targetIssueKey || (targetIssueKey = (await pluginStateManager.load()).trackerIssueKey), !targetIssueKey) {
2696
+ logger_default.warning(
2697
+ `No issue key provided and plugin has not been submitted yet. Run "${CLI_NAME} submit" first.`
2698
+ ), logger_default.suggest(`${CLI_NAME} submit`);
2699
+ return;
2700
+ }
2701
+ logger_default.info(`\u23F3 Fetching plugin info for ${targetIssueKey}...`);
2702
+ try {
2703
+ let issue = await getIssue(targetIssueKey);
2704
+ showTrackerPluginInfo(issue);
2705
+ } catch (error2) {
2706
+ throw logger_default.error(`Failed to fetch plugin info for ${targetIssueKey}`), error2;
2707
+ }
2708
+ }
2709
+ var init_info = __esm({
2710
+ "src/distributions/external/info.ts"() {
2711
+ "use strict";
2712
+ init_pluginStateManager();
2713
+ init_logger();
2714
+ init_pluginDisplay();
2715
+ init_meta();
2716
+ init_tracker();
2717
+ }
2718
+ });
2719
+
2720
+ // src/distributions/external/list.ts
2721
+ async function listExternal() {
2722
+ logger_default.info("\u23F3 Fetching my plugins from Tracker...");
2723
+ try {
2724
+ let issues = await getMyPluginIssues();
2725
+ showTrackerPluginList(issues);
2726
+ } catch (error2) {
2727
+ throw logger_default.error("Failed to fetch plugins list"), error2;
2728
+ }
2729
+ }
2730
+ var init_list = __esm({
2731
+ "src/distributions/external/list.ts"() {
2732
+ "use strict";
2733
+ init_logger();
2734
+ init_pluginDisplay();
2735
+ init_tracker();
2736
+ }
2737
+ });
2738
+
2739
+ // src/distributions/external/login.ts
2740
+ async function loginExternal() {
2741
+ console.info(
2742
+ import_picocolors3.default.dim(
2743
+ "To get an OAuth token for Yandex Tracker, please contact Tracker support and request one."
2744
+ )
2745
+ ), console.info("");
2746
+ let trimmed = (await (0, import_prompts2.input)({
2747
+ message: "Enter your OAuth token:",
2748
+ required: !0
2749
+ })).trim();
2750
+ externalAuthManager.saveAuthData(trimmed), logger_default.success("OAuth token saved successfully."), logger_default.info('You can now use "weavix submit" to submit your plugin for review.');
2751
+ }
2752
+ function logoutExternal() {
2753
+ if (!externalAuthManager.data) {
2754
+ logger_default.warning("You are not logged in.");
2755
+ return;
2756
+ }
2757
+ externalAuthManager.removeAuthData(), logger_default.success("Successfully logged out.");
2758
+ }
2759
+ var import_prompts2, import_picocolors3, init_login = __esm({
2760
+ "src/distributions/external/login.ts"() {
2761
+ "use strict";
2762
+ import_prompts2 = require("@inquirer/prompts"), import_picocolors3 = __toESM(require("picocolors"));
2763
+ init_logger();
2764
+ init_authManager();
2765
+ }
2766
+ });
2767
+
2768
+ // src/utils/execCommand.ts
2769
+ var import_execa, execCommand, init_execCommand = __esm({
2770
+ "src/utils/execCommand.ts"() {
2771
+ "use strict";
2772
+ import_execa = require("execa"), execCommand = async (command, cwd = process.cwd(), env) => {
2773
+ await (0, import_execa.execa)(command, {
2774
+ cwd,
2775
+ shell: !0,
2776
+ stdio: "inherit",
2777
+ env: env ? { ...process.env, ...env } : void 0
2778
+ });
2779
+ };
2780
+ }
2781
+ });
2782
+
2783
+ // src/commands/constants/templateCommands.ts
2784
+ var pluginCmd, init_templateCommands = __esm({
2785
+ "src/commands/constants/templateCommands.ts"() {
1368
2786
  "use strict";
1369
- import_fs4 = require("fs"), import_promises2 = require("fs/promises"), import_ajv = __toESM(require("ajv")), import_ajv_formats = __toESM(require("ajv-formats"));
1370
- init_manifestPermissionsSchema2();
1371
- init_formatValidationErrors();
1372
- init_manifest_schema();
1373
- validator = (() => {
1374
- let schema = {
1375
- ...manifest_schema_default,
1376
- properties: {
1377
- ...manifest_schema_default.properties,
1378
- permissions: {
1379
- ...manifest_schema_default.properties.permissions,
1380
- properties: {
1381
- ...manifest_schema_default.properties.permissions.properties,
1382
- ...permissionsSchemaExtensions2
1383
- }
1384
- }
1385
- }
1386
- }, ajv = new import_ajv.default({ allErrors: !0, strict: !1 });
1387
- return (0, import_ajv_formats.default)(ajv), ajv.compile(schema);
1388
- })(), manifestPath = "./manifest.json", parseManifest = (content) => {
1389
- let manifest;
1390
- try {
1391
- manifest = JSON.parse(content);
1392
- } catch (error2) {
1393
- throw error2 instanceof SyntaxError ? new Error(`File manifest.json contains invalid JSON: ${error2.message}`) : new Error(`Error reading manifest.json: ${error2.message}`);
1394
- }
1395
- return manifest;
1396
- }, loadRaw = async () => {
1397
- if (!(0, import_fs4.existsSync)(manifestPath))
1398
- throw new Error(`File manifest.json not found at path: ${manifestPath}`);
1399
- try {
1400
- return await (0, import_promises2.readFile)(manifestPath, "utf8");
1401
- } catch (error2) {
1402
- throw error2 instanceof Error ? new Error(`Error reading manifest.json: ${error2.message}`) : new Error("Error loading manifest");
1403
- }
1404
- }, load2 = async () => {
1405
- let manifestContent = await loadRaw();
1406
- return parseManifest(manifestContent);
1407
- }, validate = async () => {
1408
- let manifest = await load2();
1409
- if (!validator(manifest) && validator.errors) {
1410
- let errorMessages2 = formatValidationErrors(validator.errors);
1411
- throw new Error(
1412
- `\u274C Manifest validation failed:
1413
- ${errorMessages2}
2787
+ pluginCmd = {
2788
+ install: "npm install",
2789
+ build: "npm run build",
2790
+ dev: "npm run dev",
2791
+ lint: "npm run lint",
2792
+ typecheck: "npm run typecheck",
2793
+ test: "npm test",
2794
+ audit: "npm audit --audit-level=critical"
2795
+ };
2796
+ }
2797
+ });
1414
2798
 
1415
- \u{1F4A1} Ensure all required fields are filled according to the plugin documentation.`
1416
- );
1417
- }
1418
- }, save2 = async (manifest) => {
1419
- try {
1420
- let content = JSON.stringify(manifest, null, 4);
1421
- await (0, import_promises2.writeFile)(manifestPath, content, "utf8");
1422
- } catch (error2) {
1423
- throw error2 instanceof Error ? new Error(`Error saving manifest.json: ${error2.message}`) : new Error("Error saving manifest");
1424
- }
1425
- }, update2 = async (updates) => {
1426
- let updatedManifest = { ...await load2(), ...updates };
1427
- return await save2(updatedManifest), updatedManifest;
1428
- }, manifestManager = {
1429
- load: load2,
1430
- loadRaw,
1431
- validate,
1432
- save: save2,
1433
- update: update2
2799
+ // src/commands/build.ts
2800
+ var build, init_build = __esm({
2801
+ "src/commands/build.ts"() {
2802
+ "use strict";
2803
+ init_execCommand();
2804
+ init_logger();
2805
+ init_templateCommands();
2806
+ build = async ({ environment = "production" } = {}) => {
2807
+ logger_default.info("\u{1F528} Building project..."), await execCommand(pluginCmd.install), await execCommand(
2808
+ pluginCmd.build,
2809
+ process.cwd(),
2810
+ environment ? { VITE_DEPLOY_ENV: environment } : void 0
2811
+ );
1434
2812
  };
1435
2813
  }
1436
2814
  });
1437
2815
 
1438
2816
  // src/utils/marketplace.ts
1439
2817
  function validateMarketplaceAssets() {
1440
- let marketplaceDir = import_path3.default.resolve(MARKETPLACE_DIR);
2818
+ let marketplaceDir = import_path9.default.resolve(MARKETPLACE_DIR);
1441
2819
  ensurePathExists(
1442
2820
  marketplaceDir,
1443
2821
  "Marketplace folder not found. Create ./marketplace and add index.md and header-image.jpg before publishing."
1444
2822
  ), ensurePathExists(
1445
- import_path3.default.join(marketplaceDir, MARKETPLACE_INDEX_FILE),
2823
+ import_path9.default.join(marketplaceDir, MARKETPLACE_INDEX_FILE),
1446
2824
  "Marketplace description not found. Add ./marketplace/index.md before publishing."
1447
2825
  ), ensurePathExists(
1448
- import_path3.default.join(marketplaceDir, MARKETPLACE_HEADER_IMAGE_FILE),
2826
+ import_path9.default.join(marketplaceDir, MARKETPLACE_HEADER_IMAGE_FILE),
1449
2827
  "Marketplace header image not found. Add ./marketplace/header-image.jpg before publishing."
1450
2828
  ), ensurePathExists(
1451
- import_path3.default.resolve(PUBLIC_DIR, PUBLIC_LOGO_FILE),
2829
+ import_path9.default.resolve(PUBLIC_DIR, PUBLIC_LOGO_FILE),
1452
2830
  "Plugin logo not found. Add ./public/logo.svg before publishing."
1453
2831
  );
1454
2832
  }
1455
2833
  function validateArchiveSources() {
1456
- ensurePathExists(import_path3.default.resolve(DIST_DIR), "Dist folder not found. Build the project first."), ensurePathExists(
1457
- import_path3.default.resolve(SRC_DIR),
2834
+ ensurePathExists(import_path9.default.resolve(DIST_DIR), "Dist folder not found. Build the project first."), ensurePathExists(
2835
+ import_path9.default.resolve(SRC_DIR),
1458
2836
  "Source folder not found. Add ./src before publishing."
1459
- ), ensurePathExists(import_path3.default.resolve(MANIFEST_FILE), "manifest.json not found in plugin root."), validateMarketplaceAssets();
2837
+ ), ensurePathExists(import_path9.default.resolve(MANIFEST_FILE2), "manifest.json not found in plugin root."), validateMarketplaceAssets();
1460
2838
  }
1461
- var import_fs5, import_path3, MARKETPLACE_DIR, MARKETPLACE_INDEX_FILE, MARKETPLACE_HEADER_IMAGE_FILE, PUBLIC_DIR, PUBLIC_LOGO_FILE, MANIFEST_FILE, DIST_DIR, SRC_DIR, ensurePathExists, validateManifestPublishingFields, ensureManifestCatalogFields, marketplacePaths, init_marketplace = __esm({
2839
+ var import_fs10, import_path9, MARKETPLACE_DIR, MARKETPLACE_INDEX_FILE, MARKETPLACE_HEADER_IMAGE_FILE, PUBLIC_DIR, PUBLIC_LOGO_FILE, MANIFEST_FILE2, DIST_DIR, SRC_DIR, ensurePathExists, validateManifestPublishingFields, ensureManifestCatalogFields, marketplacePaths, init_marketplace = __esm({
1462
2840
  "src/utils/marketplace.ts"() {
1463
2841
  "use strict";
1464
- import_fs5 = __toESM(require("fs")), import_path3 = __toESM(require("path"));
2842
+ import_fs10 = __toESM(require("fs")), import_path9 = __toESM(require("path"));
1465
2843
  init_manifestManager();
1466
2844
  init_logger();
1467
- MARKETPLACE_DIR = "marketplace", MARKETPLACE_INDEX_FILE = "index.md", MARKETPLACE_HEADER_IMAGE_FILE = "header-image.jpg", PUBLIC_DIR = "public", PUBLIC_LOGO_FILE = "logo.svg", MANIFEST_FILE = "manifest.json", DIST_DIR = "dist", SRC_DIR = "src", ensurePathExists = (targetPath, errorMessage) => {
1468
- import_fs5.default.existsSync(targetPath) || (logger_default.error(errorMessage), process.exit(1));
2845
+ MARKETPLACE_DIR = "marketplace", MARKETPLACE_INDEX_FILE = "index.md", MARKETPLACE_HEADER_IMAGE_FILE = "header-image.jpg", PUBLIC_DIR = "public", PUBLIC_LOGO_FILE = "logo.svg", MANIFEST_FILE2 = "manifest.json", DIST_DIR = "dist", SRC_DIR = "src", ensurePathExists = (targetPath, errorMessage) => {
2846
+ import_fs10.default.existsSync(targetPath) || (logger_default.error(errorMessage), process.exit(1));
1469
2847
  }, validateManifestPublishingFields = async () => {
1470
2848
  let manifest = await manifestManager.load();
1471
2849
  ensureManifestCatalogFields(manifest);
@@ -1480,23 +2858,23 @@ var import_fs5, import_path3, MARKETPLACE_DIR, MARKETPLACE_INDEX_FILE, MARKETPLA
1480
2858
  distDir: DIST_DIR,
1481
2859
  srcDir: SRC_DIR,
1482
2860
  marketplaceDir: MARKETPLACE_DIR,
1483
- manifestFile: MANIFEST_FILE
2861
+ manifestFile: MANIFEST_FILE2
1484
2862
  };
1485
2863
  }
1486
2864
  });
1487
2865
 
1488
2866
  // src/utils/pluginPackageScripts.ts
1489
2867
  function readPluginPackageScripts(cwd = process.cwd()) {
1490
- let packageJsonPath = import_path4.default.join(cwd, "package.json");
1491
- return import_fs6.default.existsSync(packageJsonPath) ? JSON.parse(import_fs6.default.readFileSync(packageJsonPath, "utf-8")).scripts ?? {} : null;
2868
+ let packageJsonPath = import_path10.default.join(cwd, "package.json");
2869
+ return import_fs11.default.existsSync(packageJsonPath) ? JSON.parse(import_fs11.default.readFileSync(packageJsonPath, "utf-8")).scripts ?? {} : null;
1492
2870
  }
1493
2871
  function hasPluginScript(name, cwd = process.cwd()) {
1494
2872
  return !!readPluginPackageScripts(cwd)?.[name];
1495
2873
  }
1496
- var import_fs6, import_path4, init_pluginPackageScripts = __esm({
2874
+ var import_fs11, import_path10, init_pluginPackageScripts = __esm({
1497
2875
  "src/utils/pluginPackageScripts.ts"() {
1498
2876
  "use strict";
1499
- import_fs6 = __toESM(require("fs")), import_path4 = __toESM(require("path"));
2877
+ import_fs11 = __toESM(require("fs")), import_path10 = __toESM(require("path"));
1500
2878
  }
1501
2879
  });
1502
2880
 
@@ -1549,22 +2927,27 @@ async function buildArchive() {
1549
2927
  resolve2(buffer);
1550
2928
  }), archive.on("error", reject), archive.glob("**/*", {
1551
2929
  cwd: process.cwd(),
1552
- ignore: ["node_modules/**", "dist/**", "**/.DS_Store"],
1553
- dot: !0
1554
- }), archive.file(import_path5.default.resolve(marketplacePaths.manifestFile), { name: "src/manifest.json" }), archive.glob(
2930
+ ignore: ["node_modules/**", "dist/**"],
2931
+ dot: !1
2932
+ });
2933
+ for (let dotfile of [".npmrc", ".nvmrc"]) {
2934
+ let dotfilePath = import_path11.default.resolve(dotfile);
2935
+ import_fs12.default.existsSync(dotfilePath) && archive.file(dotfilePath, { name: dotfile });
2936
+ }
2937
+ archive.file(import_path11.default.resolve(marketplacePaths.manifestFile), { name: "src/manifest.json" }), archive.glob(
1555
2938
  "**/*",
1556
2939
  {
1557
- cwd: import_path5.default.resolve(marketplacePaths.distDir),
1558
- ignore: ["**/.DS_Store"]
2940
+ cwd: import_path11.default.resolve(marketplacePaths.distDir),
2941
+ dot: !1
1559
2942
  },
1560
2943
  { prefix: "dist/" }
1561
2944
  ), archive.finalize();
1562
2945
  });
1563
2946
  }
1564
- var import_path5, import_archiver, init_buildArchive = __esm({
2947
+ var import_fs12, import_path11, import_archiver, init_buildArchive = __esm({
1565
2948
  "src/utils/buildArchive.ts"() {
1566
2949
  "use strict";
1567
- import_path5 = __toESM(require("path")), import_archiver = __toESM(require("archiver"));
2950
+ import_fs12 = __toESM(require("fs")), import_path11 = __toESM(require("path")), import_archiver = __toESM(require("archiver"));
1568
2951
  init_manifestManager();
1569
2952
  init_meta2();
1570
2953
  init_logger();
@@ -1653,13 +3036,14 @@ function registerDistributionCommands(program) {
1653
3036
  withErrorHandling(async () => {
1654
3037
  logoutExternal();
1655
3038
  })
1656
- ), program.command("submit").description("build plugin, create a Tracker issue in PLUGINMOD, and submit for review").addOption(skipChecksOption).action(withErrorHandling(submitExternal)), program.command("list").description("list all your plugins and their moderation status").action(withErrorHandling(listExternal)), program.command("info [issue-key]").description(
3039
+ ), program.command("submit").description("build plugin, create a Tracker issue in PLUGINMOD, and submit for review").addOption(skipChecksOption).action(withErrorHandling(submitExternal)), program.command("doctor").description("validate local plugin project, external config and auth").option("--network", "verify OAuth token with Tracker /myself", !1).option("--publish", "treat publish-readiness checks as failures", !1).option("--json", "machine-readable output", !1).action((options) => withErrorHandling(doctor)(options)), program.command("list").description("list all your plugins and their moderation status").action(withErrorHandling(listExternal)), program.command("info [issue-key]").description(
1657
3040
  "show moderation status of a plugin (uses .tracker-plugin issue key if not provided)"
1658
3041
  ).action(withErrorHandling(infoExternal));
1659
3042
  }
1660
3043
  var init_registerCommands = __esm({
1661
3044
  "src/distributions/external/registerCommands.ts"() {
1662
3045
  "use strict";
3046
+ init_doctor();
1663
3047
  init_options();
1664
3048
  init_registerCommand();
1665
3049
  init_withErrorHandling();
@@ -1671,166 +3055,20 @@ var init_registerCommands = __esm({
1671
3055
  }
1672
3056
  });
1673
3057
 
1674
- // src/distributions/external/hosts.ts
1675
- var hosts_exports = {};
1676
- __export(hosts_exports, {
1677
- getBuckets: () => getBuckets,
1678
- getMdsEndpoint: () => getMdsEndpoint,
1679
- getOAuthTokenUrl: () => getOAuthTokenUrl,
1680
- getPlatformBaseUrl: () => getPlatformBaseUrl,
1681
- getPluginDownloadBase: () => getPluginDownloadBase,
1682
- getS3Endpoint: () => getS3Endpoint,
1683
- getS3Region: () => getS3Region,
1684
- getTrackerBaseUrl: () => getTrackerBaseUrl,
1685
- getUpdateCheckInfo: () => getUpdateCheckInfo
1686
- });
1687
- function requireConfig() {
1688
- let cfg = readConfig();
1689
- if (!cfg)
1690
- throw new Error('CLI is not configured. Run "weavix config set" to configure.');
1691
- return cfg;
1692
- }
1693
- function getS3Endpoint() {
1694
- let cfg = requireConfig();
1695
- if (!cfg.s3?.endpoint)
1696
- throw new Error('S3 endpoint is not configured. Run "weavix config set" to configure.');
1697
- return cfg.s3.endpoint;
1698
- }
1699
- function getMdsEndpoint() {
1700
- let cfg = requireConfig();
1701
- if (!cfg.mds?.endpoint)
1702
- throw new Error('MDS endpoint is not configured. Run "weavix config set" to configure.');
1703
- return cfg.mds.endpoint;
1704
- }
1705
- function getS3Region() {
1706
- let cfg = requireConfig();
1707
- if (!cfg.s3?.region)
1708
- throw new Error('S3 region is not configured. Run "weavix config set" to configure.');
1709
- return cfg.s3.region;
1710
- }
1711
- function getBuckets() {
1712
- let production = requireConfig().buckets?.production;
1713
- if (!production?.static || !production?.config)
1714
- throw new Error('S3 buckets are not configured. Run "weavix config set" to configure.');
1715
- let prod = { static: production.static, config: production.config };
1716
- return { testing: prod, production: prod };
1717
- }
1718
- function getPluginDownloadBase(env) {
1719
- if (env === "debug")
1720
- return "http://localhost:5173/plugins-debug";
1721
- let base = requireConfig().pluginDownloadBase?.production;
1722
- if (!base)
1723
- throw new Error(
1724
- 'Plugin download base is not configured. Run "weavix config set" to configure.'
1725
- );
1726
- return base;
1727
- }
1728
- function getPlatformBaseUrl() {
1729
- let cfg = requireConfig();
1730
- if (!cfg.api?.platformBaseUrl)
1731
- throw new Error(
1732
- 'Platform API URL is not configured. Run "weavix config set" to configure.'
1733
- );
1734
- return cfg.api.platformBaseUrl;
1735
- }
1736
- function getTrackerBaseUrl() {
1737
- return TRACKER_BASE_URL2;
1738
- }
1739
- function getOAuthTokenUrl() {
1740
- let cfg = requireConfig();
1741
- if (!cfg.auth?.oauthUrl)
1742
- throw new Error('OAuth URL is not configured. Run "weavix config set" to configure.');
1743
- return cfg.auth.oauthUrl;
1744
- }
1745
- function getUpdateCheckInfo() {
1746
- return null;
1747
- }
1748
- var TRACKER_BASE_URL2, init_hosts = __esm({
1749
- "src/distributions/external/hosts.ts"() {
1750
- "use strict";
1751
- init_manager();
1752
- TRACKER_BASE_URL2 = "https://api.tracker.yandex.net/v3";
1753
- }
1754
- });
1755
-
1756
- // src/distributions/external/templateSubstitution.ts
1757
- var templateSubstitution_exports = {};
1758
- __export(templateSubstitution_exports, {
1759
- applySubstitutions: () => applySubstitutions,
1760
- overlayDirName: () => overlayDirName,
1761
- templateDeps: () => templateDeps
1762
- });
1763
- function rewritePackageJson(content) {
1764
- let pkg = JSON.parse(content);
1765
- if (pkg.dependencies) {
1766
- let next = {};
1767
- for (let [name, version] of Object.entries(pkg.dependencies)) {
1768
- let renamed = PACKAGE_RENAME[name] ?? name;
1769
- next[renamed] = ADDED_DEPS[renamed] ?? version;
1770
- }
1771
- for (let [name, version] of Object.entries(ADDED_DEPS))
1772
- name in next || (next[name] = version);
1773
- pkg.dependencies = Object.fromEntries(
1774
- Object.entries(next).sort(([a], [b]) => a.localeCompare(b))
1775
- );
1776
- }
1777
- return JSON.stringify(pkg, null, 4) + `
1778
- `;
1779
- }
1780
- function rewriteImports(content) {
1781
- let result = content;
1782
- for (let [from, to] of Object.entries(PACKAGE_RENAME)) {
1783
- let escaped = from.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1784
- result = result.replace(new RegExp(escaped, "g"), to);
1785
- }
1786
- return result;
1787
- }
1788
- function rewriteNpmrc(content) {
1789
- return content.split(`
1790
- `).filter((line) => !/^registry\s*=\s*https?:\/\/npm\.yandex-team\.ru/.test(line.trim())).join(`
1791
- `);
1792
- }
1793
- function applySubstitutions(filePath, content) {
1794
- let name = import_path6.default.basename(filePath), ext = import_path6.default.extname(filePath);
1795
- if (name === "package.json")
1796
- return Buffer.from(rewritePackageJson(content.toString("utf8")), "utf8");
1797
- if (name === "npmrc.template" || name === ".npmrc")
1798
- return Buffer.from(rewriteNpmrc(content.toString("utf8")), "utf8");
1799
- if ([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"].includes(ext)) {
1800
- let original = content.toString("utf8"), rewritten = rewriteImports(original);
1801
- if (rewritten !== original)
1802
- return Buffer.from(rewritten, "utf8");
1803
- }
1804
- return content;
1805
- }
1806
- var import_path6, PACKAGE_RENAME, ADDED_DEPS, templateDeps, overlayDirName, init_templateSubstitution = __esm({
1807
- "src/distributions/external/templateSubstitution.ts"() {
1808
- "use strict";
1809
- import_path6 = __toESM(require("path")), PACKAGE_RENAME = {
1810
- "@yandex-data-ui/tracker-plugin-sdk-react": "@weavix/sdk-react",
1811
- "@yandex-data-ui/tracker-pub-api-types": "@weavix/tracker-api-types"
1812
- }, ADDED_DEPS = {
1813
- "@weavix/sdk-core": "latest",
1814
- "@weavix/sdk-react": "latest",
1815
- "@weavix/tracker-api-types": "latest"
1816
- }, templateDeps = ["@weavix/sdk-core", "@weavix/sdk-react", "@weavix/tracker-api-types"], overlayDirName = "_external";
1817
- }
1818
- });
1819
-
1820
3058
  // src/index.ts
1821
3059
  var import_commander2 = require("commander");
1822
3060
  init_meta2();
1823
3061
 
1824
3062
  // src/distribution/registerCommands.ts
1825
3063
  init_flag();
1826
- var impl3 = (init_registerCommands(), __toCommonJS(registerCommands_exports)), { registerDistributionCommands: registerDistributionCommands2 } = impl3;
3064
+ var impl4 = (init_registerCommands(), __toCommonJS(registerCommands_exports)), { registerDistributionCommands: registerDistributionCommands2 } = impl4;
1827
3065
 
1828
3066
  // src/utils/checkUpdate.ts
1829
3067
  var import_node_fetch2 = __toESM(require("node-fetch"));
1830
3068
 
1831
3069
  // src/distribution/hosts.ts
1832
3070
  init_flag();
1833
- var impl4 = (init_hosts(), __toCommonJS(hosts_exports)), {
3071
+ var impl5 = (init_hosts(), __toCommonJS(hosts_exports)), {
1834
3072
  getS3Endpoint: getS3Endpoint2,
1835
3073
  getMdsEndpoint: getMdsEndpoint2,
1836
3074
  getS3Region: getS3Region2,
@@ -1840,7 +3078,7 @@ var impl4 = (init_hosts(), __toCommonJS(hosts_exports)), {
1840
3078
  getTrackerBaseUrl: getTrackerBaseUrl2,
1841
3079
  getOAuthTokenUrl: getOAuthTokenUrl2,
1842
3080
  getUpdateCheckInfo: getUpdateCheckInfo2
1843
- } = impl4;
3081
+ } = impl5;
1844
3082
 
1845
3083
  // src/utils/checkUpdate.ts
1846
3084
  init_logger();
@@ -1877,131 +3115,33 @@ Run: ${installCmd}`);
1877
3115
  }
1878
3116
  };
1879
3117
 
3118
+ // src/utils/shouldRunUpdateCheck.ts
3119
+ function shouldRunUpdateCheck(argv) {
3120
+ return !(argv.includes("doctor") && argv.includes("--json"));
3121
+ }
3122
+
1880
3123
  // src/index.ts
1881
3124
  init_build();
1882
3125
 
1883
3126
  // src/commands/create/index.ts
1884
- var path13 = __toESM(require("path")), import_prompts3 = require("@inquirer/prompts");
1885
-
1886
- // src/core/manifest/constants.ts
1887
- var DATA_PERMISSIONS = [
1888
- // top 10
1889
- "tracker:issues:read",
1890
- "tracker:issues:write",
1891
- "tracker:issuetypes:read",
1892
- "tracker:statuses:read",
1893
- "tracker:queues:read",
1894
- "tracker:fields:read",
1895
- "tracker:entities:read",
1896
- "tracker:attachments:read",
1897
- "tracker:attachments:write",
1898
- // in alphabetical order
1899
- "tracker:applications:read",
1900
- "tracker:boards:read",
1901
- "tracker:boards:write",
1902
- "tracker:bulk:read",
1903
- "tracker:bulk:write",
1904
- "tracker:bulkchange:read",
1905
- "tracker:bulkchange:write",
1906
- "tracker:charts:read",
1907
- "tracker:commentTemplates:read",
1908
- "tracker:commentTemplates:write",
1909
- "tracker:components:read",
1910
- "tracker:components:write",
1911
- "tracker:data:read",
1912
- "tracker:departments:read",
1913
- "tracker:entities:write",
1914
- "tracker:externalEventTypes:write",
1915
- "tracker:externalEvents:write",
1916
- "tracker:fields:write",
1917
- "tracker:filterFolders:write",
1918
- "tracker:filters:read",
1919
- "tracker:filters:write",
1920
- "tracker:goals:read",
1921
- "tracker:goals:write",
1922
- "tracker:groups:read",
1923
- "tracker:issueTemplates:read",
1924
- "tracker:issueTemplates:write",
1925
- "tracker:links:read",
1926
- "tracker:linktypes:read",
1927
- "tracker:liveBoards:write",
1928
- "tracker:localFields:read",
1929
- "tracker:maillists:read",
1930
- "tracker:maillists:write",
1931
- "tracker:myself:read",
1932
- "tracker:myself:write",
1933
- "tracker:priorities:read",
1934
- "tracker:queues:write",
1935
- "tracker:reminders:read",
1936
- "tracker:reminders:write",
1937
- "tracker:remotelinks:read",
1938
- "tracker:reports:read",
1939
- "tracker:reports:write",
1940
- "tracker:resolutions:read",
1941
- "tracker:resources:read",
1942
- "tracker:resources:write",
1943
- "tracker:roles:read",
1944
- "tracker:screens:read",
1945
- "tracker:services:read",
1946
- "tracker:sprints:read",
1947
- "tracker:sprints:write",
1948
- "tracker:system:write",
1949
- "tracker:tags:read",
1950
- "tracker:translations:read",
1951
- "tracker:users:read",
1952
- "tracker:users:write",
1953
- "tracker:versions:read",
1954
- "tracker:versions:write",
1955
- "tracker:workflows:read",
1956
- "tracker:workflows:write",
1957
- "tracker:worklog:read",
1958
- "tracker:worklog:write"
1959
- ], TOP_DATA_PERMISSIONS = DATA_PERMISSIONS.slice(0, 10);
1960
- var TEMPLATES = [
1961
- "default",
1962
- "issue.action",
1963
- "issue.block",
1964
- "issue.tab",
1965
- "issue.comment.action",
1966
- "navigation",
1967
- "trigger.action",
1968
- "project.action",
1969
- "project.block",
1970
- "project.tab",
1971
- "portfolio.action",
1972
- "portfolio.block",
1973
- "portfolio.tab",
1974
- "goal.action",
1975
- "goal.block",
1976
- "goal.tab",
1977
- "attachment.viewer.action",
1978
- "board.tab"
1979
- ];
1980
- var TEMPLATE_SLOTS = {
1981
- default: [],
1982
- "issue.action": ["issue.action"],
1983
- "issue.block": ["issue.block"],
1984
- "issue.tab": ["issue.tab"],
1985
- "issue.comment.action": ["issue.comment.action"],
1986
- navigation: ["navigation"],
1987
- "trigger.action": ["trigger.create.action", "trigger.edit.action"],
1988
- "project.action": ["project.action"],
1989
- "project.block": ["project.block"],
1990
- "project.tab": ["project.tab"],
1991
- "portfolio.action": ["portfolio.action"],
1992
- "portfolio.block": ["portfolio.block"],
1993
- "portfolio.tab": ["portfolio.tab"],
1994
- "goal.action": ["goal.action"],
1995
- "goal.block": ["goal.block"],
1996
- "goal.tab": ["goal.tab"],
1997
- "attachment.viewer.action": ["attachment.viewer.action"],
1998
- "board.tab": ["board.tab"]
1999
- };
2000
-
2001
- // src/commands/create/index.ts
3127
+ var path18 = __toESM(require("path")), import_prompts3 = require("@inquirer/prompts");
3128
+ init_constants();
2002
3129
  init_meta2();
2003
3130
  init_logger();
2004
3131
 
3132
+ // src/commands/create/templateChoices.ts
3133
+ init_constants();
3134
+ var DEFERRED_TEMPLATE_REASON = "will be added later", DEFERRED_TEMPLATES = /* @__PURE__ */ new Set(["user-card-info", "user-card-calendar"]);
3135
+ function getTemplateChoices(service) {
3136
+ return TEMPLATES.filter((templateName) => TEMPLATE_SERVICE[templateName] === service).map(
3137
+ (templateName) => ({
3138
+ name: templateName,
3139
+ value: templateName,
3140
+ disabled: DEFERRED_TEMPLATES.has(templateName) ? DEFERRED_TEMPLATE_REASON : void 0
3141
+ })
3142
+ );
3143
+ }
3144
+
2005
3145
  // src/commands/create/utils/getWelcomeMessage.ts
2006
3146
  var import_picocolors5 = __toESM(require("picocolors")), getWelcomeMessage = (pwd) => `
2007
3147
  ${import_picocolors5.default.bold(import_picocolors5.default.white("\u{1F680} Create new tracker plugin"))}
@@ -2012,25 +3152,27 @@ ${import_picocolors5.default.dim("Press")} ${import_picocolors5.default.yellow("
2012
3152
  `;
2013
3153
 
2014
3154
  // src/commands/create/utils/initManifest.ts
2015
- var fs5 = __toESM(require("fs")), path7 = __toESM(require("path"));
3155
+ var fs11 = __toESM(require("fs")), path13 = __toESM(require("path"));
2016
3156
 
2017
3157
  // src/commands/create/utils/generateManifest.ts
3158
+ init_constants();
3159
+ var FULL_CONTEXT_TEMPLATES = /* @__PURE__ */ new Set(["user-card-info", "user-card-calendar"]);
2018
3160
  function buildSlots(template, slotTitle) {
2019
3161
  let slotNames = TEMPLATE_SLOTS[template];
2020
3162
  if (slotNames.length === 0) return;
2021
- let slotEntry = {
3163
+ let service = TEMPLATE_SERVICE[template], contextLevel = FULL_CONTEXT_TEMPLATES.has(template) ? "full" : "basic", slotEntry = {
2022
3164
  entrypoint: "index.html",
2023
3165
  title: { ru: slotTitle, en: slotTitle },
2024
- contextLevel: "basic"
3166
+ contextLevel
2025
3167
  };
2026
3168
  return {
2027
- tracker: Object.fromEntries(slotNames.map((slotName) => [slotName, [slotEntry]]))
3169
+ [service]: Object.fromEntries(slotNames.map((slotName) => [slotName, [slotEntry]]))
2028
3170
  };
2029
3171
  }
2030
3172
  var generateManifest = (answers) => ({
2031
3173
  $schema: "./manifest.schema.json",
2032
3174
  manifest_version: 1,
2033
- supported_services: ["tracker"],
3175
+ supported_services: [TEMPLATE_SERVICE[answers.template]],
2034
3176
  slug: answers.packageSlug,
2035
3177
  version: answers.version,
2036
3178
  name: {
@@ -2048,55 +3190,58 @@ var generateManifest = (answers) => ({
2048
3190
 
2049
3191
  // src/commands/create/utils/initManifest.ts
2050
3192
  var initManifest = ({ answers, targetDir }) => {
2051
- let generatedManifest = generateManifest(answers), manifestPath2 = path7.join(targetDir, "manifest.json");
2052
- fs5.writeFileSync(manifestPath2, JSON.stringify(generatedManifest, null, 2), "utf-8");
3193
+ let generatedManifest = generateManifest(answers), manifestPath = path13.join(targetDir, "manifest.json");
3194
+ fs11.writeFileSync(manifestPath, JSON.stringify(generatedManifest, null, 2), "utf-8");
2053
3195
  };
2054
3196
 
2055
3197
  // src/commands/create/utils/initTemplate.ts
2056
- var fs8 = __toESM(require("fs")), path12 = __toESM(require("path"));
3198
+ var fs14 = __toESM(require("fs")), path17 = __toESM(require("path"));
2057
3199
 
2058
3200
  // src/distribution/templateSubstitution.ts
2059
3201
  init_flag();
2060
- var impl5 = (init_templateSubstitution(), __toCommonJS(templateSubstitution_exports)), { applySubstitutions: applySubstitutions2, overlayDirName: overlayDirName2, templateDeps: templateDeps2 } = impl5;
3202
+ var isInternal = !1, templateDeps = [
3203
+ "@weavix/tracker-plugin-sdk",
3204
+ "@weavix/tracker-plugin-sdk-react",
3205
+ "@weavix/tracker-api-types"
3206
+ ], overlayDirName = isInternal ? "_internal" : "_external";
2061
3207
 
2062
3208
  // src/utils/copyDirectory.ts
2063
- var fs6 = __toESM(require("fs")), import_path7 = __toESM(require("path")), import_tinyglobby = require("tinyglobby");
2064
- var resolveTargetFileName = (file) => file.endsWith(".template") ? "." + file.replace(".template", "") : file, copyDirectory = async (sourceDir, targetDir) => {
2065
- let files = await (0, import_tinyglobby.glob)(["**/*"], {
3209
+ var fs12 = __toESM(require("fs")), import_path12 = __toESM(require("path")), import_tinyglobby2 = require("tinyglobby"), resolveTargetFileName = (file) => file.endsWith(".template") ? "." + file.replace(".template", "") : file, copyDirectory = async (sourceDir, targetDir) => {
3210
+ let files = await (0, import_tinyglobby2.glob)(["**/*"], {
2066
3211
  cwd: sourceDir,
2067
3212
  onlyFiles: !0,
2068
3213
  dot: !0
2069
3214
  });
2070
3215
  await Promise.all(
2071
3216
  files.map(async (file) => {
2072
- let sourcePath = import_path7.default.join(sourceDir, file), targetFile = resolveTargetFileName(file), targetPath = import_path7.default.join(targetDir, targetFile);
2073
- await fs6.promises.mkdir(import_path7.default.dirname(targetPath), { recursive: !0 });
2074
- let content = await fs6.promises.readFile(sourcePath), rewritten = applySubstitutions2(file, content);
2075
- await fs6.promises.writeFile(targetPath, rewritten);
3217
+ let sourcePath = import_path12.default.join(sourceDir, file), targetFile = resolveTargetFileName(file), targetPath = import_path12.default.join(targetDir, targetFile);
3218
+ await fs12.promises.mkdir(import_path12.default.dirname(targetPath), { recursive: !0 });
3219
+ let content = await fs12.promises.readFile(sourcePath);
3220
+ await fs12.promises.writeFile(targetPath, content);
2076
3221
  })
2077
3222
  );
2078
3223
  };
2079
3224
 
2080
3225
  // src/utils/getProjectPath.ts
2081
- var import_path8 = __toESM(require("path")), isDevelopment = () => __dirname.includes("/src/"), getProjectPath = (relativePath) => isDevelopment() ? import_path8.default.resolve(__dirname, "..", "..", relativePath) : import_path8.default.resolve(__dirname, relativePath), getTemplatesBaseDir = () => getProjectPath("templates"), getTemplatePath = (filename) => import_path8.default.join(getTemplatesBaseDir(), "_shared", filename);
3226
+ var import_path13 = __toESM(require("path")), isDevelopment = () => __dirname.includes("/src/"), getProjectPath = (relativePath) => isDevelopment() ? import_path13.default.resolve(__dirname, "..", "..", relativePath) : import_path13.default.resolve(__dirname, relativePath), getTemplatesBaseDir = () => getProjectPath("templates"), getTemplatePath = (filename) => import_path13.default.join(getTemplatesBaseDir(), "_shared", filename), getOverlayTemplatePath = (overlayDir, filename) => import_path13.default.join(getTemplatesBaseDir(), overlayDir, filename);
2082
3227
 
2083
3228
  // src/commands/create/utils/initTemplate.ts
2084
3229
  init_logger();
2085
3230
 
2086
3231
  // src/commands/create/utils/updatePackageJson.ts
2087
- var fs7 = __toESM(require("fs")), path11 = __toESM(require("path")), updatePackageJson = (targetDir, packageSlug) => {
2088
- let packageJsonPath = path11.join(targetDir, "package.json");
2089
- if (fs7.existsSync(packageJsonPath)) {
2090
- let packageJson = JSON.parse(fs7.readFileSync(packageJsonPath, "utf-8"));
2091
- packageJson.name = packageSlug, fs7.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 4) + `
3232
+ var fs13 = __toESM(require("fs")), path16 = __toESM(require("path")), updatePackageJson = (targetDir, packageSlug) => {
3233
+ let packageJsonPath = path16.join(targetDir, "package.json");
3234
+ if (fs13.existsSync(packageJsonPath)) {
3235
+ let packageJson = JSON.parse(fs13.readFileSync(packageJsonPath, "utf-8"));
3236
+ packageJson.name = packageSlug, fs13.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 4) + `
2092
3237
  `);
2093
3238
  }
2094
3239
  };
2095
3240
 
2096
3241
  // src/commands/create/utils/initTemplate.ts
2097
3242
  var initTemplate = async ({ answers, targetDir }) => {
2098
- fs8.existsSync(targetDir) || fs8.mkdirSync(targetDir, { recursive: !0 });
2099
- let templatesBaseDir = getTemplatesBaseDir(), templatesDir = path12.join(templatesBaseDir, answers.template), sharedDir = path12.join(templatesBaseDir, "_shared"), overlayDir = path12.join(templatesBaseDir, overlayDirName2);
3243
+ fs14.existsSync(targetDir) || fs14.mkdirSync(targetDir, { recursive: !0 });
3244
+ let templatesBaseDir = getTemplatesBaseDir(), templatesDir = path17.join(templatesBaseDir, answers.template), sharedDir = path17.join(templatesBaseDir, "_shared"), overlayDir = path17.join(templatesBaseDir, overlayDirName);
2100
3245
  await copyDirectory(sharedDir, targetDir), await copyDirectory(overlayDir, targetDir), await copyDirectory(templatesDir, targetDir), updatePackageJson(targetDir, answers.packageSlug), logger_default.info("Created template with marketplace publication requirements."), logger_default.info(
2101
3246
  "Before publishing, add ./marketplace/index.md, ./marketplace/header-image.jpg (784:325), and ./public/logo.svg (square)."
2102
3247
  );
@@ -2119,12 +3264,23 @@ async function create() {
2119
3264
  message: "Enter support email:",
2120
3265
  required: !0,
2121
3266
  validate: (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value) || "Please enter a valid email address"
2122
- }), template = await (0, import_prompts3.select)({
2123
- message: "Select a template:",
2124
- choices: TEMPLATES.map((templateName) => ({
2125
- name: templateName,
2126
- value: templateName
3267
+ }), service = CREATE_SERVICES2.length === 1 ? CREATE_SERVICES2[0] : await (0, import_prompts3.select)({
3268
+ message: "Select a service:",
3269
+ choices: CREATE_SERVICES2.map((serviceName) => ({
3270
+ name: serviceName,
3271
+ value: serviceName
2127
3272
  }))
3273
+ }), templateChoices = getTemplateChoices(service);
3274
+ if (templateChoices.every((choice) => choice.disabled)) {
3275
+ logger_default.warning(`No selectable templates are available for ${service} yet.`), logger_default.info(
3276
+ templateChoices.map((choice) => `- ${choice.name} ${choice.disabled ?? ""}`.trim()).join(`
3277
+ `)
3278
+ );
3279
+ return;
3280
+ }
3281
+ let template = await (0, import_prompts3.select)({
3282
+ message: "Select a template:",
3283
+ choices: templateChoices
2128
3284
  }), dataPermissions = await (0, import_prompts3.checkbox)({
2129
3285
  message: "Select data permissions (some popular options):",
2130
3286
  choices: TOP_DATA_PERMISSIONS.map((permission) => ({
@@ -2137,25 +3293,26 @@ async function create() {
2137
3293
  pluginName,
2138
3294
  pluginDescription,
2139
3295
  supportEmail,
3296
+ service,
2140
3297
  template,
2141
3298
  permissions: {
2142
3299
  data: dataPermissions
2143
3300
  },
2144
3301
  version: DEFAULT_VERSION
2145
- }, targetDir = path13.join(process.cwd(), answers.packageSlug);
3302
+ }, targetDir = path18.join(process.cwd(), answers.packageSlug);
2146
3303
  await initTemplate({
2147
3304
  answers,
2148
3305
  targetDir
2149
3306
  }), initManifest({
2150
3307
  answers,
2151
3308
  targetDir
2152
- }), logger_default.newLine(), logger_default.success("\u2705 Plugin created successfully!"), logger_default.newLine(), logger_default.info("\u{1F680} To start development:"), logger_default.commands("", [`cd ${answers.packageSlug}`, "npm install", `${CLI_NAME2} debug`]), logger_default.newLine(), logger_default.info(
2153
- "\u{1F4CC} Important: After running debug, the plugin will be available in the Tracker interface,"
2154
- ), logger_default.info("not at localhost. Open Tracker and check the plugin in the appropriate context.");
3309
+ }), logger_default.newLine(), logger_default.success("\u2705 Plugin created successfully!"), logger_default.info("\u{1F680} To start development:"), logger_default.commands("", [`cd ${answers.packageSlug}`, "npm install", `${CLI_NAME2} debug`]), logger_default.info(
3310
+ "\u{1F4CC} Important: After running debug, the plugin will be available in the Tracker interface, not at localhost. Open Tracker and check the plugin in the appropriate context."
3311
+ );
2155
3312
  }
2156
3313
 
2157
3314
  // src/commands/debug/index.ts
2158
- var import_fs10 = __toESM(require("fs")), import_path12 = __toESM(require("path"));
3315
+ var import_fs16 = __toESM(require("fs")), import_path17 = __toESM(require("path"));
2159
3316
  init_manifestManager();
2160
3317
 
2161
3318
  // src/core/s3config/constants.ts
@@ -2179,7 +3336,7 @@ var registerCleanup = (cleanup) => {
2179
3336
  init_templateCommands();
2180
3337
 
2181
3338
  // src/commands/debug/utils/createDebugConfig.ts
2182
- var import_fs7 = __toESM(require("fs")), import_path9 = __toESM(require("path"));
3339
+ var import_fs13 = __toESM(require("fs")), import_path14 = __toESM(require("path"));
2183
3340
  init_manifestManager();
2184
3341
 
2185
3342
  // src/utils/convertManifestToConfig.ts
@@ -2226,21 +3383,21 @@ var convertManifestToConfig = (manifest, environment) => {
2226
3383
 
2227
3384
  // src/commands/debug/utils/createDebugConfig.ts
2228
3385
  var createDebugConfig = async () => {
2229
- let manifest = await manifestManager.load(), config = convertManifestToConfig(manifest, "debug"), configPath = import_path9.default.join(process.cwd(), CONFIG_FILE_NAME);
2230
- import_fs7.default.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
3386
+ let manifest = await manifestManager.load(), config = convertManifestToConfig(manifest, "debug"), configPath = import_path14.default.join(process.cwd(), CONFIG_FILE_NAME);
3387
+ import_fs13.default.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
2231
3388
  };
2232
3389
 
2233
3390
  // src/commands/debug/utils/lockFile.ts
2234
- var import_fs8 = __toESM(require("fs")), import_path10 = __toESM(require("path")), LOCK_FILE_NAME = ".tracker-cli-debug.lock", getLockFilePath = () => import_path10.default.join(process.cwd(), LOCK_FILE_NAME), getRunningDebugPid = () => {
3391
+ var import_fs14 = __toESM(require("fs")), import_path15 = __toESM(require("path")), LOCK_FILE_NAME = ".yaweavix-debug.lock", getLockFilePath = () => import_path15.default.join(process.cwd(), LOCK_FILE_NAME), getRunningDebugPid = () => {
2235
3392
  let lockPath = getLockFilePath();
2236
- if (!import_fs8.default.existsSync(lockPath))
3393
+ if (!import_fs14.default.existsSync(lockPath))
2237
3394
  return null;
2238
3395
  try {
2239
- let pid = JSON.parse(import_fs8.default.readFileSync(lockPath, "utf-8")).pid;
3396
+ let pid = JSON.parse(import_fs14.default.readFileSync(lockPath, "utf-8")).pid;
2240
3397
  return process.kill(pid, 0), pid;
2241
3398
  } catch {
2242
3399
  try {
2243
- import_fs8.default.unlinkSync(lockPath);
3400
+ import_fs14.default.unlinkSync(lockPath);
2244
3401
  } catch {
2245
3402
  }
2246
3403
  return null;
@@ -2248,19 +3405,19 @@ var import_fs8 = __toESM(require("fs")), import_path10 = __toESM(require("path")
2248
3405
  }, createLockFile = () => {
2249
3406
  let lockPath = getLockFilePath(), lockData = {
2250
3407
  pid: process.pid
2251
- }, fd = import_fs8.default.openSync(lockPath, "wx");
2252
- import_fs8.default.writeSync(fd, JSON.stringify(lockData, null, 2)), import_fs8.default.closeSync(fd);
3408
+ }, fd = import_fs14.default.openSync(lockPath, "wx");
3409
+ import_fs14.default.writeSync(fd, JSON.stringify(lockData, null, 2)), import_fs14.default.closeSync(fd);
2253
3410
  }, removeLockFile = () => {
2254
3411
  let lockPath = getLockFilePath();
2255
- import_fs8.default.existsSync(lockPath) && import_fs8.default.unlinkSync(lockPath);
3412
+ import_fs14.default.existsSync(lockPath) && import_fs14.default.unlinkSync(lockPath);
2256
3413
  };
2257
3414
 
2258
3415
  // src/commands/debug/utils/watchManifest.ts
2259
- var import_fs9 = __toESM(require("fs")), import_path11 = __toESM(require("path"));
3416
+ var import_fs15 = __toESM(require("fs")), import_path16 = __toESM(require("path"));
2260
3417
  init_manifestManager();
2261
3418
  init_logger();
2262
3419
  var watchManifest = () => {
2263
- let manifestPath2 = import_path11.default.join(process.cwd(), "manifest.json"), debounceTimer = null, watcher = import_fs9.default.watch(manifestPath2, async (eventType) => {
3420
+ let manifestPath = import_path16.default.join(process.cwd(), "manifest.json"), debounceTimer = null, watcher = import_fs15.default.watch(manifestPath, async (eventType) => {
2264
3421
  eventType === "change" && (debounceTimer && clearTimeout(debounceTimer), debounceTimer = setTimeout(async () => {
2265
3422
  try {
2266
3423
  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");
@@ -2284,10 +3441,10 @@ Please stop the existing instance before starting a new one.
2284
3441
  If you lost the terminal tab, you can kill the process with:
2285
3442
  kill ${runningPid}`
2286
3443
  ), process.exit(1));
2287
- let configPath = import_path12.default.join(process.cwd(), CONFIG_FILE_NAME);
3444
+ let configPath = import_path17.default.join(process.cwd(), CONFIG_FILE_NAME);
2288
3445
  options.lint && await manifestManager.validate(), await createDebugConfig();
2289
3446
  let watcher = watchManifest(), cleanup = () => {
2290
- watcher.close(), import_fs10.default.existsSync(configPath) && import_fs10.default.unlinkSync(configPath), removeLockFile();
3447
+ watcher.close(), import_fs16.default.existsSync(configPath) && import_fs16.default.unlinkSync(configPath), removeLockFile();
2291
3448
  };
2292
3449
  registerCleanup(cleanup), createLockFile(), logger_default.newLine(), logger_default.info("\u{1F527} Debug mode started!"), logger_default.newLine(), logger_default.info("\u{1F4CC} The plugin is now available in the Tracker interface."), logger_default.info("Open Tracker and check the plugin functionality in the appropriate context."), logger_default.newLine(), logger_default.info("\u26A0\uFE0F Do not try to open localhost in the browser - the plugin works"), logger_default.info("only inside Tracker through a special loading mechanism."), logger_default.newLine(), logger_default.info("\u{1F504} Code changes will be automatically reloaded."), logger_default.info("Press Ctrl+C to stop."), logger_default.newLine(), await execCommand(pluginCmd.dev), cleanup();
2293
3450
  }
@@ -2301,19 +3458,23 @@ async function lint() {
2301
3458
  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);
2302
3459
  }
2303
3460
 
3461
+ // src/commands/up/index.ts
3462
+ var import_fs19 = require("fs"), import_promises5 = require("fs/promises");
3463
+ init_execCommand();
3464
+
2304
3465
  // src/commands/up/utils/copyTemplateFiles.ts
2305
- var import_fs11 = require("fs"), import_promises3 = require("fs/promises");
2306
- var copyTemplateFiles = async (filenames) => {
3466
+ var import_fs17 = require("fs"), import_promises3 = require("fs/promises"), import_path18 = __toESM(require("path"));
3467
+ var copyTemplateFiles = async (files) => {
2307
3468
  await Promise.all(
2308
- filenames.map(async (filename) => {
2309
- let templatePath = getTemplatePath(filename), targetPath = `./${filename}`;
2310
- if ((0, import_fs11.existsSync)(templatePath) && (0, import_fs11.existsSync)(targetPath)) {
2311
- let content = await (0, import_promises3.readFile)(templatePath), rewritten = applySubstitutions2(filename, content);
2312
- await (0, import_promises3.writeFile)(targetPath, rewritten);
2313
- }
3469
+ files.map(async (file) => {
3470
+ let templatePath, targetPath, force = !1;
3471
+ typeof file == "string" ? (templatePath = getTemplatePath(file), targetPath = `./${file}`) : (templatePath = file.sourcePath ?? getTemplatePath(file.source ?? file.target), targetPath = `./${file.target}`, force = file.force ?? !1), (0, import_fs17.existsSync)(templatePath) && (force || (0, import_fs17.existsSync)(targetPath)) && (await (0, import_promises3.mkdir)(import_path18.default.dirname(targetPath), { recursive: !0 }), await (0, import_promises3.copyFile)(templatePath, targetPath));
2314
3472
  })
2315
3473
  );
2316
- };
3474
+ }, overlayFileCopy = (overlayDir, sourceFilename, targetFilename) => ({
3475
+ sourcePath: getOverlayTemplatePath(overlayDir, sourceFilename),
3476
+ target: targetFilename
3477
+ });
2317
3478
 
2318
3479
  // src/commands/up/utils/updateManifestCompatibility.ts
2319
3480
  init_manifestManager();
@@ -2337,15 +3498,12 @@ async function updateManifestCompatibility() {
2337
3498
  }
2338
3499
 
2339
3500
  // src/commands/up/utils/updatePackageDependencies.ts
2340
- var import_fs12 = require("fs"), import_promises4 = require("fs/promises");
3501
+ var import_fs18 = require("fs"), import_promises4 = require("fs/promises");
2341
3502
  var updatePackageDependencies = async (dependencies) => {
2342
3503
  let packageJsonPath = "./package.json", templatePackageJsonPath = getTemplatePath("package.json");
2343
- if (!(0, import_fs12.existsSync)(packageJsonPath) || !(0, import_fs12.existsSync)(templatePackageJsonPath))
3504
+ if (!(0, import_fs18.existsSync)(packageJsonPath) || !(0, import_fs18.existsSync)(templatePackageJsonPath))
2344
3505
  return;
2345
- let packageJsonContent = await (0, import_promises4.readFile)(packageJsonPath, "utf-8"), templatePackageJsonRaw = await (0, import_promises4.readFile)(templatePackageJsonPath), templatePackageJsonContent = applySubstitutions2(
2346
- "package.json",
2347
- templatePackageJsonRaw
2348
- ).toString("utf8"), packageJson = JSON.parse(packageJsonContent), templatePackageJson = JSON.parse(templatePackageJsonContent), updated = !1;
3506
+ let packageJsonContent = await (0, import_promises4.readFile)(packageJsonPath, "utf-8"), templatePackageJsonContent = await (0, import_promises4.readFile)(templatePackageJsonPath, "utf-8"), packageJson = JSON.parse(packageJsonContent), templatePackageJson = JSON.parse(templatePackageJsonContent), updated = !1;
2349
3507
  dependencies.forEach((dep) => {
2350
3508
  packageJson.dependencies?.[dep] && templatePackageJson.dependencies?.[dep] && packageJson.dependencies[dep] !== templatePackageJson.dependencies[dep] && (packageJson.dependencies[dep] = templatePackageJson.dependencies[dep], updated = !0);
2351
3509
  }), updated && await (0, import_promises4.writeFile)(packageJsonPath, JSON.stringify(packageJson, null, 4) + `
@@ -2353,18 +3511,36 @@ var updatePackageDependencies = async (dependencies) => {
2353
3511
  };
2354
3512
 
2355
3513
  // src/commands/up/index.ts
2356
- var templateFiles = ["manifest.schema.json", "vite.config.ts"];
3514
+ var npmrcPath = "./.npmrc", npmrcTemplateFilename = "npmrc.template", sharedFiles = [
3515
+ "manifest.schema.json",
3516
+ "vite.config.ts",
3517
+ { source: "proxy.ts", target: "proxy.ts", force: !0 }
3518
+ ];
3519
+ async function isNpmrcOutdated() {
3520
+ let templatePath = getOverlayTemplatePath(overlayDirName, npmrcTemplateFilename);
3521
+ if (!(0, import_fs19.existsSync)(npmrcPath) || !(0, import_fs19.existsSync)(templatePath))
3522
+ return !1;
3523
+ let [currentNpmrc, templateNpmrc] = await Promise.all([
3524
+ (0, import_promises5.readFile)(npmrcPath, "utf-8"),
3525
+ (0, import_promises5.readFile)(templatePath, "utf-8")
3526
+ ]);
3527
+ return currentNpmrc !== templateNpmrc;
3528
+ }
2357
3529
  async function up() {
2358
- await copyTemplateFiles(templateFiles), await updateManifestCompatibility(), await updatePackageDependencies(templateDeps2);
3530
+ let shouldCleanNpmCache = await isNpmrcOutdated();
3531
+ await copyTemplateFiles([
3532
+ ...sharedFiles,
3533
+ { ...overlayFileCopy(overlayDirName, npmrcTemplateFilename, ".npmrc"), force: !0 }
3534
+ ]), await updateManifestCompatibility(), await updatePackageDependencies(templateDeps), shouldCleanNpmCache && await execCommand("npm cache clean --force"), await execCommand("npm i");
2359
3535
  }
2360
3536
 
2361
3537
  // src/utils/getVersion.ts
2362
- var import_fs13 = require("fs"), import_path13 = require("path"), UNKNOWN_VERSION = "unknown", CANDIDATES = ["..", "../.."], findVersionInPackageJson = (startDir) => {
3538
+ var import_fs20 = require("fs"), import_path19 = require("path"), UNKNOWN_VERSION = "unknown", CANDIDATES = ["..", "../.."], findVersionInPackageJson = (startDir) => {
2363
3539
  for (let rel of CANDIDATES) {
2364
- let path18 = (0, import_path13.resolve)(startDir, rel, "package.json");
2365
- if ((0, import_fs13.existsSync)(path18))
3540
+ let path24 = (0, import_path19.resolve)(startDir, rel, "package.json");
3541
+ if ((0, import_fs20.existsSync)(path24))
2366
3542
  try {
2367
- let pkg = JSON.parse((0, import_fs13.readFileSync)(path18, "utf-8"));
3543
+ let pkg = JSON.parse((0, import_fs20.readFileSync)(path24, "utf-8"));
2368
3544
  if (typeof pkg.version == "string") return pkg.version;
2369
3545
  } catch {
2370
3546
  }
@@ -2377,10 +3553,10 @@ init_verbose();
2377
3553
  init_withErrorHandling();
2378
3554
  async function main() {
2379
3555
  let program = new import_commander2.Command(), version = getVersion();
2380
- await checkUpdate(version), program.name(CLI_NAME2).description(CLI_DESCRIPTION2).version(version).option("--verbose", "enable verbose output"), CLI_HELP_TEXT2 && program.addHelpText("before", CLI_HELP_TEXT2), program.hook("preAction", (thisCommand) => {
3556
+ shouldRunUpdateCheck(process.argv.slice(2)) && await checkUpdate(version), program.name(CLI_NAME2).description(CLI_DESCRIPTION2).version(version).option("--verbose", "enable verbose output"), CLI_HELP_TEXT2 && program.addHelpText("before", CLI_HELP_TEXT2), program.hook("preAction", (thisCommand) => {
2381
3557
  setVerboseEnabled(!!thisCommand.opts().verbose);
2382
3558
  }), 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(
2383
3559
  "start a tunnel to connect your local code with the app running in the development environment"
2384
- ).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);
3560
+ ).option("--no-lint", "skip lint validation").action((options) => withErrorHandling(debug)(options)), program.command("lint").description("run TypeScript and ESLint checks").action(withErrorHandling(lint)), registerDistributionCommands2(program), await program.parseAsync(), process.exit(typeof process.exitCode == "number" ? process.exitCode : 0);
2385
3561
  }
2386
3562
  main();