@weavix/cli 0.1.0-dev → 0.2.0-dev
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.js
CHANGED
|
@@ -40,6 +40,24 @@ var CLI_NAME, CLI_DESCRIPTION, CLI_HELP_TEXT, init_meta = __esm({
|
|
|
40
40
|
}
|
|
41
41
|
});
|
|
42
42
|
|
|
43
|
+
// src/utils/verbose.ts
|
|
44
|
+
function setVerboseEnabled(value) {
|
|
45
|
+
verboseEnabled = value;
|
|
46
|
+
}
|
|
47
|
+
function isVerboseEnabled() {
|
|
48
|
+
return verboseEnabled;
|
|
49
|
+
}
|
|
50
|
+
function writeVerboseArtifact(relativePath, content) {
|
|
51
|
+
let targetPath = import_path.default.resolve(".tracker-cli-debug", relativePath);
|
|
52
|
+
return import_fs.default.mkdirSync(import_path.default.dirname(targetPath), { recursive: !0 }), import_fs.default.writeFileSync(targetPath, content), targetPath;
|
|
53
|
+
}
|
|
54
|
+
var import_fs, import_path, verboseEnabled, init_verbose = __esm({
|
|
55
|
+
"src/utils/verbose.ts"() {
|
|
56
|
+
"use strict";
|
|
57
|
+
import_fs = __toESM(require("fs")), import_path = __toESM(require("path")), verboseEnabled = !1;
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
43
61
|
// src/utils/logger.ts
|
|
44
62
|
function success(message) {
|
|
45
63
|
console.info(import_picocolors.default.green(`\u2705 ${message}`)), newLine();
|
|
@@ -54,6 +72,9 @@ function warning(message) {
|
|
|
54
72
|
function info(message) {
|
|
55
73
|
console.info(message), newLine();
|
|
56
74
|
}
|
|
75
|
+
function verbose(message) {
|
|
76
|
+
isVerboseEnabled() && (console.info(import_picocolors.default.dim(message)), newLine());
|
|
77
|
+
}
|
|
57
78
|
function suggest(command) {
|
|
58
79
|
console.info(`Run: ${command}`), newLine();
|
|
59
80
|
}
|
|
@@ -73,11 +94,13 @@ var import_picocolors, logger, logger_default, init_logger = __esm({
|
|
|
73
94
|
"src/utils/logger.ts"() {
|
|
74
95
|
"use strict";
|
|
75
96
|
import_picocolors = __toESM(require("picocolors"));
|
|
97
|
+
init_verbose();
|
|
76
98
|
logger = {
|
|
77
99
|
success,
|
|
78
100
|
error,
|
|
79
101
|
warning,
|
|
80
102
|
info,
|
|
103
|
+
verbose,
|
|
81
104
|
suggest,
|
|
82
105
|
newLine,
|
|
83
106
|
separator,
|
|
@@ -86,102 +109,112 @@ var import_picocolors, logger, logger_default, init_logger = __esm({
|
|
|
86
109
|
}
|
|
87
110
|
});
|
|
88
111
|
|
|
89
|
-
// src/distributions/external/
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
112
|
+
// src/distributions/external/config/configManager.ts
|
|
113
|
+
function getConfigPath() {
|
|
114
|
+
return CONFIG_FILE;
|
|
115
|
+
}
|
|
116
|
+
function readConfig() {
|
|
117
|
+
if (cached !== void 0)
|
|
118
|
+
return cached;
|
|
119
|
+
if (!(0, import_fs2.existsSync)(CONFIG_FILE))
|
|
120
|
+
return cached = null, cached;
|
|
121
|
+
try {
|
|
122
|
+
cached = JSON.parse((0, import_fs2.readFileSync)(CONFIG_FILE, "utf-8"));
|
|
123
|
+
} catch {
|
|
124
|
+
cached = null;
|
|
125
|
+
}
|
|
126
|
+
return cached;
|
|
127
|
+
}
|
|
128
|
+
function writeConfig(config) {
|
|
129
|
+
(0, import_fs2.existsSync)(CONFIG_DIR) || (0, import_fs2.mkdirSync)(CONFIG_DIR, { recursive: !0, mode: 448 }), (0, import_fs2.writeFileSync)(CONFIG_FILE, JSON.stringify(config, null, 2), { mode: 384 }), cached = config;
|
|
95
130
|
}
|
|
96
|
-
|
|
97
|
-
(0,
|
|
131
|
+
function clearConfig() {
|
|
132
|
+
(0, import_fs2.existsSync)(CONFIG_FILE) && (0, import_fs2.rmSync)(CONFIG_FILE), cached = null;
|
|
98
133
|
}
|
|
99
|
-
|
|
100
|
-
|
|
134
|
+
function requireConfig() {
|
|
135
|
+
let config = readConfig();
|
|
136
|
+
if (!config)
|
|
137
|
+
throw new Error('CLI is not configured. Run "weavix config set" to configure.');
|
|
138
|
+
return config;
|
|
101
139
|
}
|
|
102
|
-
var
|
|
103
|
-
"src/distributions/external/
|
|
140
|
+
var import_fs2, os, import_path2, CONFIG_DIR, CONFIG_FILE, cached, init_configManager = __esm({
|
|
141
|
+
"src/distributions/external/config/configManager.ts"() {
|
|
104
142
|
"use strict";
|
|
105
|
-
|
|
143
|
+
import_fs2 = require("fs"), os = __toESM(require("os")), import_path2 = __toESM(require("path")), CONFIG_DIR = import_path2.default.join(os.homedir(), ".tracker-cli"), CONFIG_FILE = import_path2.default.join(CONFIG_DIR, "config.json");
|
|
106
144
|
}
|
|
107
145
|
});
|
|
108
146
|
|
|
109
|
-
// src/distributions/external/
|
|
110
|
-
function
|
|
111
|
-
return
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
let
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
147
|
+
// src/distributions/external/config/index.ts
|
|
148
|
+
async function promptString(message, current, required = !0) {
|
|
149
|
+
return (await (0, import_prompts.input)({
|
|
150
|
+
message: current ? `${message} (current: ${current})` : message,
|
|
151
|
+
default: current,
|
|
152
|
+
required: required && !current
|
|
153
|
+
}))?.trim() || void 0;
|
|
154
|
+
}
|
|
155
|
+
async function runConfigSet() {
|
|
156
|
+
let existing = readConfig() ?? {};
|
|
157
|
+
logger_default.info("Configure CLI endpoints. Empty input keeps the current value.");
|
|
158
|
+
let s3Endpoint = await promptString("S3 endpoint", existing.s3?.endpoint), s3Region = await promptString("S3 region", existing.s3?.region), mdsEndpoint = await promptString("MDS endpoint", existing.mds?.endpoint), testingStatic = await promptString(
|
|
159
|
+
"Testing bucket (static)",
|
|
160
|
+
existing.buckets?.testing?.static
|
|
161
|
+
), testingConfig = await promptString(
|
|
162
|
+
"Testing bucket (config)",
|
|
163
|
+
existing.buckets?.testing?.config
|
|
164
|
+
), productionStatic = await promptString(
|
|
165
|
+
"Production bucket (static)",
|
|
166
|
+
existing.buckets?.production?.static
|
|
167
|
+
), productionConfig = await promptString(
|
|
168
|
+
"Production bucket (config)",
|
|
169
|
+
existing.buckets?.production?.config
|
|
170
|
+
), pluginDownloadTesting = await promptString(
|
|
171
|
+
"Plugin download base URL (testing)",
|
|
172
|
+
existing.pluginDownloadBase?.testing
|
|
173
|
+
), pluginDownloadProduction = await promptString(
|
|
174
|
+
"Plugin download base URL (production)",
|
|
175
|
+
existing.pluginDownloadBase?.production
|
|
176
|
+
), platformBaseUrl = await promptString(
|
|
177
|
+
"Platform API base URL",
|
|
178
|
+
existing.api?.platformBaseUrl
|
|
179
|
+
), trackerBaseUrl = await promptString("Tracker API base URL", existing.api?.trackerBaseUrl), oauthUrl = await promptString("OAuth token URL", existing.auth?.oauthUrl);
|
|
180
|
+
writeConfig({
|
|
181
|
+
s3: { endpoint: s3Endpoint, region: s3Region },
|
|
182
|
+
mds: { endpoint: mdsEndpoint },
|
|
183
|
+
buckets: {
|
|
184
|
+
testing: { static: testingStatic, config: testingConfig },
|
|
185
|
+
production: { static: productionStatic, config: productionConfig }
|
|
186
|
+
},
|
|
187
|
+
pluginDownloadBase: {
|
|
188
|
+
testing: pluginDownloadTesting,
|
|
189
|
+
production: pluginDownloadProduction
|
|
190
|
+
},
|
|
191
|
+
api: { platformBaseUrl, trackerBaseUrl },
|
|
192
|
+
auth: { oauthUrl }
|
|
193
|
+
}), logger_default.success(`Configuration saved \u2192 ${getConfigPath()}`);
|
|
152
194
|
}
|
|
153
|
-
|
|
154
|
-
let cfg =
|
|
195
|
+
function runConfigShow() {
|
|
196
|
+
let cfg = readConfig();
|
|
155
197
|
if (!cfg) {
|
|
156
|
-
logger_default.info(
|
|
198
|
+
logger_default.info(
|
|
199
|
+
`No configuration found at ${getConfigPath()}. Run "weavix config set" to create one.`
|
|
200
|
+
);
|
|
157
201
|
return;
|
|
158
202
|
}
|
|
159
|
-
logger_default.info(JSON.stringify(cfg, null, 2));
|
|
203
|
+
logger_default.info(`Configuration at ${getConfigPath()}:`), logger_default.info(JSON.stringify(cfg, null, 2));
|
|
160
204
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
logger_default.info("No configuration to clear.");
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
if (!await (0, import_prompts.confirm)({
|
|
167
|
-
message: `Remove configuration at ${CONFIG_FILE_PATH}?`,
|
|
168
|
-
default: !1
|
|
169
|
-
})) {
|
|
170
|
-
logger_default.info("Cancelled.");
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
await clearConfig(), logger_default.success("Configuration removed.");
|
|
205
|
+
function runConfigClear() {
|
|
206
|
+
clearConfig(), logger_default.success(`Configuration removed (${getConfigPath()})`);
|
|
174
207
|
}
|
|
175
208
|
function registerConfigCommand(program) {
|
|
176
|
-
let config = program.command("config").description("manage CLI configuration
|
|
177
|
-
config.command("set").description("set configuration interactively").action(
|
|
209
|
+
let config = program.command("config").description("manage CLI configuration");
|
|
210
|
+
config.command("set").description("set CLI configuration values interactively").action(runConfigSet), config.command("show").description("display current CLI configuration").action(runConfigShow), config.command("clear").description("remove stored CLI configuration").action(runConfigClear);
|
|
178
211
|
}
|
|
179
|
-
var import_prompts,
|
|
180
|
-
"src/distributions/external/
|
|
212
|
+
var import_prompts, init_config = __esm({
|
|
213
|
+
"src/distributions/external/config/index.ts"() {
|
|
181
214
|
"use strict";
|
|
182
215
|
import_prompts = require("@inquirer/prompts");
|
|
183
216
|
init_logger();
|
|
184
|
-
|
|
217
|
+
init_configManager();
|
|
185
218
|
}
|
|
186
219
|
});
|
|
187
220
|
|
|
@@ -196,92 +229,85 @@ function registerDistributionCommands(program) {
|
|
|
196
229
|
var init_registerCommands = __esm({
|
|
197
230
|
"src/distributions/external/registerCommands.ts"() {
|
|
198
231
|
"use strict";
|
|
199
|
-
|
|
232
|
+
init_config();
|
|
200
233
|
}
|
|
201
234
|
});
|
|
202
235
|
|
|
203
|
-
// src/distributions/external/
|
|
204
|
-
var
|
|
205
|
-
__export(
|
|
206
|
-
|
|
207
|
-
|
|
236
|
+
// src/distributions/external/hosts.ts
|
|
237
|
+
var hosts_exports = {};
|
|
238
|
+
__export(hosts_exports, {
|
|
239
|
+
getBuckets: () => getBuckets,
|
|
240
|
+
getMdsEndpoint: () => getMdsEndpoint,
|
|
241
|
+
getOAuthTokenUrl: () => getOAuthTokenUrl,
|
|
242
|
+
getPlatformBaseUrl: () => getPlatformBaseUrl,
|
|
243
|
+
getPluginDownloadBase: () => getPluginDownloadBase,
|
|
244
|
+
getS3Endpoint: () => getS3Endpoint,
|
|
245
|
+
getS3Region: () => getS3Region,
|
|
246
|
+
getTrackerBaseUrl: () => getTrackerBaseUrl,
|
|
247
|
+
getUpdateCheckInfo: () => getUpdateCheckInfo
|
|
208
248
|
});
|
|
209
|
-
|
|
249
|
+
function getS3Endpoint() {
|
|
250
|
+
let cfg = requireConfig();
|
|
251
|
+
if (!cfg.s3?.endpoint)
|
|
252
|
+
throw new Error('S3 endpoint is not configured. Run "weavix config set" to configure.');
|
|
253
|
+
return cfg.s3.endpoint;
|
|
254
|
+
}
|
|
255
|
+
function getMdsEndpoint() {
|
|
256
|
+
let cfg = requireConfig();
|
|
257
|
+
if (!cfg.mds?.endpoint)
|
|
258
|
+
throw new Error('MDS endpoint is not configured. Run "weavix config set" to configure.');
|
|
259
|
+
return cfg.mds.endpoint;
|
|
260
|
+
}
|
|
261
|
+
function getS3Region() {
|
|
262
|
+
let cfg = requireConfig();
|
|
263
|
+
if (!cfg.s3?.region)
|
|
264
|
+
throw new Error('S3 region is not configured. Run "weavix config set" to configure.');
|
|
265
|
+
return cfg.s3.region;
|
|
266
|
+
}
|
|
267
|
+
function getBuckets() {
|
|
268
|
+
let buckets = requireConfig().buckets, testing = buckets?.testing, production = buckets?.production;
|
|
269
|
+
if (!testing?.static || !testing?.config || !production?.static || !production?.config)
|
|
270
|
+
throw new Error('S3 buckets are not configured. Run "weavix config set" to configure.');
|
|
271
|
+
return {
|
|
272
|
+
testing: { static: testing.static, config: testing.config },
|
|
273
|
+
production: { static: production.static, config: production.config }
|
|
274
|
+
};
|
|
210
275
|
}
|
|
211
|
-
|
|
276
|
+
function getPluginDownloadBase(env) {
|
|
277
|
+
let base = requireConfig().pluginDownloadBase?.[env];
|
|
278
|
+
if (!base)
|
|
279
|
+
throw new Error(
|
|
280
|
+
`Plugin download base for "${env}" is not configured. Run "weavix config set" to configure.`
|
|
281
|
+
);
|
|
282
|
+
return base;
|
|
212
283
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
var apiUrls_exports = {};
|
|
221
|
-
__export(apiUrls_exports, {
|
|
222
|
-
getPlatformApiUrl: () => getPlatformApiUrl,
|
|
223
|
-
getTrackerApiUrl: () => getTrackerApiUrl
|
|
224
|
-
});
|
|
225
|
-
async function getPlatformApiUrl() {
|
|
226
|
-
let cfg = await readConfig();
|
|
227
|
-
if (!cfg?.platformApiUrl)
|
|
228
|
-
throw new Error("Platform API URL is not configured. Run: tracker-cli config set");
|
|
229
|
-
return cfg.platformApiUrl;
|
|
230
|
-
}
|
|
231
|
-
async function getTrackerApiUrl() {
|
|
232
|
-
let cfg = await readConfig();
|
|
233
|
-
if (!cfg?.trackerApiUrl)
|
|
234
|
-
throw new Error("Tracker API URL is not configured. Run: tracker-cli config set");
|
|
235
|
-
return cfg.trackerApiUrl;
|
|
236
|
-
}
|
|
237
|
-
var init_apiUrls = __esm({
|
|
238
|
-
"src/distributions/external/apiUrls.ts"() {
|
|
239
|
-
"use strict";
|
|
240
|
-
init_configStore();
|
|
241
|
-
}
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
// src/distributions/external/promptEnvironment.ts
|
|
245
|
-
var promptEnvironment_exports = {};
|
|
246
|
-
__export(promptEnvironment_exports, {
|
|
247
|
-
promptEnvironment: () => promptEnvironment
|
|
248
|
-
});
|
|
249
|
-
async function promptEnvironment() {
|
|
250
|
-
return "";
|
|
284
|
+
function getPlatformBaseUrl() {
|
|
285
|
+
let cfg = requireConfig();
|
|
286
|
+
if (!cfg.api?.platformBaseUrl)
|
|
287
|
+
throw new Error(
|
|
288
|
+
'Platform API URL is not configured. Run "weavix config set" to configure.'
|
|
289
|
+
);
|
|
290
|
+
return cfg.api.platformBaseUrl;
|
|
251
291
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
listEnvironments: () => listEnvironments
|
|
264
|
-
});
|
|
265
|
-
async function getStorageSettings(_environment) {
|
|
266
|
-
let cfg = await readConfig();
|
|
267
|
-
if (!cfg)
|
|
268
|
-
throw new Error("CLI is not configured. Run: tracker-cli config set");
|
|
269
|
-
return {
|
|
270
|
-
awsEndpoint: cfg.awsEndpoint,
|
|
271
|
-
awsRegion: cfg.awsRegion,
|
|
272
|
-
mdsEndpoint: cfg.mdsEndpoint ?? cfg.awsEndpoint,
|
|
273
|
-
configBucket: cfg.configBucket,
|
|
274
|
-
staticBucket: cfg.staticBucket
|
|
275
|
-
};
|
|
292
|
+
function getTrackerBaseUrl() {
|
|
293
|
+
let cfg = requireConfig();
|
|
294
|
+
if (!cfg.api?.trackerBaseUrl)
|
|
295
|
+
throw new Error('Tracker API URL is not configured. Run "weavix config set" to configure.');
|
|
296
|
+
return cfg.api.trackerBaseUrl;
|
|
297
|
+
}
|
|
298
|
+
function getOAuthTokenUrl() {
|
|
299
|
+
let cfg = requireConfig();
|
|
300
|
+
if (!cfg.auth?.oauthUrl)
|
|
301
|
+
throw new Error('OAuth URL is not configured. Run "weavix config set" to configure.');
|
|
302
|
+
return cfg.auth.oauthUrl;
|
|
276
303
|
}
|
|
277
|
-
|
|
278
|
-
return
|
|
304
|
+
function getUpdateCheckInfo() {
|
|
305
|
+
return null;
|
|
279
306
|
}
|
|
280
|
-
var
|
|
281
|
-
"src/distributions/external/
|
|
307
|
+
var init_hosts = __esm({
|
|
308
|
+
"src/distributions/external/hosts.ts"() {
|
|
282
309
|
"use strict";
|
|
283
|
-
|
|
284
|
-
DEFAULT_ENVIRONMENT = "";
|
|
310
|
+
init_configManager();
|
|
285
311
|
}
|
|
286
312
|
});
|
|
287
313
|
|
|
@@ -297,26 +323,35 @@ var impl2 = (init_registerCommands(), __toCommonJS(registerCommands_exports)), {
|
|
|
297
323
|
// src/utils/checkUpdate.ts
|
|
298
324
|
var import_node_fetch = __toESM(require("node-fetch"));
|
|
299
325
|
|
|
300
|
-
// src/distribution/
|
|
301
|
-
var impl3 = (
|
|
326
|
+
// src/distribution/hosts.ts
|
|
327
|
+
var impl3 = (init_hosts(), __toCommonJS(hosts_exports)), {
|
|
328
|
+
getS3Endpoint: getS3Endpoint2,
|
|
329
|
+
getMdsEndpoint: getMdsEndpoint2,
|
|
330
|
+
getS3Region: getS3Region2,
|
|
331
|
+
getBuckets: getBuckets2,
|
|
332
|
+
getPluginDownloadBase: getPluginDownloadBase2,
|
|
333
|
+
getPlatformBaseUrl: getPlatformBaseUrl2,
|
|
334
|
+
getTrackerBaseUrl: getTrackerBaseUrl2,
|
|
335
|
+
getOAuthTokenUrl: getOAuthTokenUrl2,
|
|
336
|
+
getUpdateCheckInfo: getUpdateCheckInfo2
|
|
337
|
+
} = impl3;
|
|
302
338
|
|
|
303
339
|
// src/utils/checkUpdate.ts
|
|
304
340
|
init_logger();
|
|
305
341
|
var checkUpdate = async (version) => {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
}
|
|
342
|
+
let info3 = getUpdateCheckInfo2();
|
|
343
|
+
if (info3)
|
|
344
|
+
try {
|
|
345
|
+
let response = await (0, import_node_fetch.default)(`${info3.registryUrl}/${info3.packageName}/latest`);
|
|
346
|
+
if (!response.ok)
|
|
347
|
+
return;
|
|
348
|
+
let latest = await response.json();
|
|
349
|
+
latest.version !== version && (logger_default.newLine(), logger_default.info(
|
|
350
|
+
`\u{1F514} Update available ${version} \u2192 ${latest.version}
|
|
351
|
+
Run: npm i -g ${info3.packageName}@latest --registry=${info3.registryUrl}`
|
|
352
|
+
));
|
|
353
|
+
} catch {
|
|
354
|
+
}
|
|
320
355
|
};
|
|
321
356
|
|
|
322
357
|
// src/utils/execCommand.ts
|
|
@@ -346,173 +381,269 @@ var build = async ({ environment = "production" } = {}) => {
|
|
|
346
381
|
);
|
|
347
382
|
};
|
|
348
383
|
|
|
349
|
-
// src/
|
|
350
|
-
var
|
|
384
|
+
// src/commands/create/index.ts
|
|
385
|
+
var path8 = __toESM(require("path")), import_prompts2 = require("@inquirer/prompts");
|
|
351
386
|
|
|
352
|
-
// src/
|
|
353
|
-
var
|
|
387
|
+
// src/core/manifest/constants.ts
|
|
388
|
+
var DATA_PERMISSIONS = [
|
|
389
|
+
// top 10
|
|
390
|
+
"tracker:issues:read",
|
|
391
|
+
"tracker:issues:write",
|
|
392
|
+
"tracker:issuetypes:read",
|
|
393
|
+
"tracker:statuses:read",
|
|
394
|
+
"tracker:queues:read",
|
|
395
|
+
"tracker:fields:read",
|
|
396
|
+
"tracker:entities:read",
|
|
397
|
+
"tracker:attachments:read",
|
|
398
|
+
"tracker:attachments:write",
|
|
399
|
+
// in alphabetical order
|
|
400
|
+
"tracker:applications:read",
|
|
401
|
+
"tracker:boards:read",
|
|
402
|
+
"tracker:boards:write",
|
|
403
|
+
"tracker:bulk:read",
|
|
404
|
+
"tracker:bulk:write",
|
|
405
|
+
"tracker:bulkchange:read",
|
|
406
|
+
"tracker:bulkchange:write",
|
|
407
|
+
"tracker:charts:read",
|
|
408
|
+
"tracker:commentTemplates:read",
|
|
409
|
+
"tracker:commentTemplates:write",
|
|
410
|
+
"tracker:components:read",
|
|
411
|
+
"tracker:components:write",
|
|
412
|
+
"tracker:data:read",
|
|
413
|
+
"tracker:departments:read",
|
|
414
|
+
"tracker:entities:write",
|
|
415
|
+
"tracker:externalEventTypes:write",
|
|
416
|
+
"tracker:externalEvents:write",
|
|
417
|
+
"tracker:fields:write",
|
|
418
|
+
"tracker:filterFolders:write",
|
|
419
|
+
"tracker:filters:read",
|
|
420
|
+
"tracker:filters:write",
|
|
421
|
+
"tracker:goals:read",
|
|
422
|
+
"tracker:goals:write",
|
|
423
|
+
"tracker:groups:read",
|
|
424
|
+
"tracker:issueTemplates:read",
|
|
425
|
+
"tracker:issueTemplates:write",
|
|
426
|
+
"tracker:links:read",
|
|
427
|
+
"tracker:linktypes:read",
|
|
428
|
+
"tracker:liveBoards:write",
|
|
429
|
+
"tracker:localFields:read",
|
|
430
|
+
"tracker:maillists:read",
|
|
431
|
+
"tracker:maillists:write",
|
|
432
|
+
"tracker:myself:read",
|
|
433
|
+
"tracker:myself:write",
|
|
434
|
+
"tracker:priorities:read",
|
|
435
|
+
"tracker:queues:write",
|
|
436
|
+
"tracker:reminders:read",
|
|
437
|
+
"tracker:reminders:write",
|
|
438
|
+
"tracker:remotelinks:read",
|
|
439
|
+
"tracker:reports:read",
|
|
440
|
+
"tracker:reports:write",
|
|
441
|
+
"tracker:resolutions:read",
|
|
442
|
+
"tracker:resources:read",
|
|
443
|
+
"tracker:resources:write",
|
|
444
|
+
"tracker:roles:read",
|
|
445
|
+
"tracker:screens:read",
|
|
446
|
+
"tracker:services:read",
|
|
447
|
+
"tracker:sprints:read",
|
|
448
|
+
"tracker:sprints:write",
|
|
449
|
+
"tracker:system:write",
|
|
450
|
+
"tracker:tags:read",
|
|
451
|
+
"tracker:translations:read",
|
|
452
|
+
"tracker:users:read",
|
|
453
|
+
"tracker:users:write",
|
|
454
|
+
"tracker:versions:read",
|
|
455
|
+
"tracker:versions:write",
|
|
456
|
+
"tracker:workflows:read",
|
|
457
|
+
"tracker:workflows:write",
|
|
458
|
+
"tracker:worklog:read",
|
|
459
|
+
"tracker:worklog:write"
|
|
460
|
+
], TOP_DATA_PERMISSIONS = DATA_PERMISSIONS.slice(0, 10);
|
|
461
|
+
var TEMPLATES = [
|
|
462
|
+
"default",
|
|
463
|
+
"issue.action",
|
|
464
|
+
"issue.block",
|
|
465
|
+
"issue.tab",
|
|
466
|
+
"issue.comment.action",
|
|
467
|
+
"navigation",
|
|
468
|
+
"trigger.action",
|
|
469
|
+
"project.action",
|
|
470
|
+
"portfolio.action",
|
|
471
|
+
"goal.action",
|
|
472
|
+
"issue.floatingbottom.action",
|
|
473
|
+
"attachment.viewer.action"
|
|
474
|
+
];
|
|
475
|
+
var TEMPLATE_SLOTS = {
|
|
476
|
+
default: [],
|
|
477
|
+
"issue.action": ["issue.action"],
|
|
478
|
+
"issue.block": ["issue.block"],
|
|
479
|
+
"issue.tab": ["issue.tab"],
|
|
480
|
+
"issue.comment.action": ["issue.comment.action"],
|
|
481
|
+
navigation: ["navigation"],
|
|
482
|
+
"trigger.action": ["trigger.create.action", "trigger.edit.action"],
|
|
483
|
+
"project.action": ["project.action"],
|
|
484
|
+
"portfolio.action": ["portfolio.action"],
|
|
485
|
+
"goal.action": ["goal.action"],
|
|
486
|
+
"issue.floatingbottom.action": ["issue.floatingbottom.action"],
|
|
487
|
+
"attachment.viewer.action": ["attachment.viewer.action"]
|
|
488
|
+
};
|
|
354
489
|
|
|
355
|
-
// src/
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
490
|
+
// src/commands/create/index.ts
|
|
491
|
+
init_logger();
|
|
492
|
+
|
|
493
|
+
// src/commands/create/utils/getWelcomeMessage.ts
|
|
494
|
+
var import_picocolors2 = __toESM(require("picocolors")), getWelcomeMessage = (pwd) => `
|
|
495
|
+
${import_picocolors2.default.bold(import_picocolors2.default.white("\u{1F680} Create new tracker plugin"))}
|
|
496
|
+
|
|
497
|
+
${import_picocolors2.default.dim(`\u{1F4C1} Creating an app in your current directory: ${pwd}`)}
|
|
498
|
+
|
|
499
|
+
${import_picocolors2.default.dim("Press")} ${import_picocolors2.default.yellow("Ctrl+C")} ${import_picocolors2.default.dim("to cancel.")}
|
|
500
|
+
`;
|
|
501
|
+
|
|
502
|
+
// src/commands/create/utils/initManifest.ts
|
|
503
|
+
var fs2 = __toESM(require("fs")), path3 = __toESM(require("path"));
|
|
504
|
+
|
|
505
|
+
// src/commands/create/utils/generateManifest.ts
|
|
506
|
+
function buildSlots(template, slotTitle) {
|
|
507
|
+
let slotNames = TEMPLATE_SLOTS[template];
|
|
508
|
+
if (slotNames.length === 0) return;
|
|
509
|
+
let slotEntry = {
|
|
510
|
+
entrypoint: "index.html",
|
|
511
|
+
title: { ru: slotTitle, en: slotTitle }
|
|
371
512
|
};
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
513
|
+
return {
|
|
514
|
+
tracker: Object.fromEntries(slotNames.map((slotName) => [slotName, [slotEntry]]))
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
var generateManifest = (answers) => ({
|
|
518
|
+
$schema: "./manifest.schema.json",
|
|
519
|
+
manifest_version: 1,
|
|
520
|
+
supported_services: ["tracker"],
|
|
521
|
+
slug: answers.packageSlug,
|
|
522
|
+
version: answers.version,
|
|
523
|
+
name: {
|
|
524
|
+
ru: answers.pluginName,
|
|
525
|
+
en: answers.pluginName
|
|
380
526
|
},
|
|
381
|
-
|
|
382
|
-
|
|
527
|
+
description: {
|
|
528
|
+
ru: answers.pluginDescription,
|
|
529
|
+
en: answers.pluginDescription
|
|
383
530
|
},
|
|
384
|
-
|
|
385
|
-
|
|
531
|
+
permissions: answers.permissions,
|
|
532
|
+
support: [{ type: "email", value: answers.supportEmail }],
|
|
533
|
+
slots: buildSlots(answers.template, answers.slotTitle)
|
|
534
|
+
});
|
|
535
|
+
|
|
536
|
+
// src/commands/create/utils/initManifest.ts
|
|
537
|
+
var initManifest = ({ answers, targetDir }) => {
|
|
538
|
+
let generatedManifest = generateManifest(answers), manifestPath2 = path3.join(targetDir, "manifest.json");
|
|
539
|
+
fs2.writeFileSync(manifestPath2, JSON.stringify(generatedManifest, null, 2), "utf-8");
|
|
386
540
|
};
|
|
387
541
|
|
|
388
|
-
// src/
|
|
389
|
-
var
|
|
542
|
+
// src/commands/create/utils/initTemplate.ts
|
|
543
|
+
var fs5 = __toESM(require("fs")), path7 = __toESM(require("path"));
|
|
390
544
|
|
|
391
|
-
// src/
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
params.append(key, String(value));
|
|
398
|
-
}), `?${params.toString()}`;
|
|
399
|
-
}
|
|
400
|
-
async function parseResponse(response) {
|
|
401
|
-
return response.status === 204 || response.headers.get("content-length") === "0" ? void 0 : response.headers.get("content-type")?.includes("application/json") ? await response.json() : await response.text();
|
|
402
|
-
}
|
|
403
|
-
async function trackerApiRequest(endpoint, options = {}) {
|
|
404
|
-
let { method = "GET", body, headers = {}, formData, queryParams } = options, authHeader = authManager.authHeader;
|
|
405
|
-
if (!authHeader)
|
|
406
|
-
throw new Error('Not authenticated. Run "tracker-cli login" first.');
|
|
407
|
-
let requestHeaders = {
|
|
408
|
-
Authorization: authHeader,
|
|
409
|
-
Accept: "application/json",
|
|
410
|
-
...headers
|
|
411
|
-
}, requestBody;
|
|
412
|
-
if (formData) {
|
|
413
|
-
let formHeaders = formData.getHeaders?.();
|
|
414
|
-
Object.assign(requestHeaders, formHeaders), requestBody = formData;
|
|
415
|
-
} else body && method !== "GET" && (requestHeaders["Content-Type"] = "application/json", requestBody = JSON.stringify(body));
|
|
416
|
-
let queryString = buildQueryString(queryParams), url = `${await getTrackerApiUrl2()}${endpoint}${queryString}`, response = await (0, import_node_fetch2.default)(url, {
|
|
417
|
-
method,
|
|
418
|
-
headers: requestHeaders,
|
|
419
|
-
body: requestBody
|
|
545
|
+
// src/utils/copyDirectory.ts
|
|
546
|
+
var fs3 = __toESM(require("fs")), import_path3 = __toESM(require("path")), import_tinyglobby = require("tinyglobby"), resolveTargetFileName = (file) => file.endsWith(".template") ? "." + file.replace(".template", "") : file, copyDirectory = async (sourceDir, targetDir) => {
|
|
547
|
+
let files = await (0, import_tinyglobby.glob)(["**/*"], {
|
|
548
|
+
cwd: sourceDir,
|
|
549
|
+
onlyFiles: !0,
|
|
550
|
+
dot: !0
|
|
420
551
|
});
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
throw new Error(errorMessage);
|
|
429
|
-
}
|
|
430
|
-
return parseResponse(response);
|
|
431
|
-
}
|
|
552
|
+
await Promise.all(
|
|
553
|
+
files.map(async (file) => {
|
|
554
|
+
let sourcePath = import_path3.default.join(sourceDir, file), targetFile = resolveTargetFileName(file), targetPath = import_path3.default.join(targetDir, targetFile);
|
|
555
|
+
await fs3.promises.mkdir(import_path3.default.dirname(targetPath), { recursive: !0 }), await fs3.promises.copyFile(sourcePath, targetPath);
|
|
556
|
+
})
|
|
557
|
+
);
|
|
558
|
+
};
|
|
432
559
|
|
|
433
|
-
// src/
|
|
434
|
-
var
|
|
435
|
-
|
|
436
|
-
return
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
560
|
+
// src/utils/getProjectPath.ts
|
|
561
|
+
var import_path4 = __toESM(require("path")), isDevelopment = () => __dirname.includes("/src/"), getProjectPath = (relativePath) => {
|
|
562
|
+
let levelsUp = isDevelopment() ? "../.." : "..";
|
|
563
|
+
return import_path4.default.resolve(__dirname, levelsUp, relativePath);
|
|
564
|
+
}, getTemplatesBaseDir = () => getProjectPath("templates"), getTemplatePath = (filename) => import_path4.default.join(getTemplatesBaseDir(), "_shared", filename);
|
|
565
|
+
|
|
566
|
+
// src/commands/create/utils/initTemplate.ts
|
|
567
|
+
init_logger();
|
|
568
|
+
|
|
569
|
+
// src/commands/create/utils/updatePackageJson.ts
|
|
570
|
+
var fs4 = __toESM(require("fs")), path6 = __toESM(require("path")), updatePackageJson = (targetDir, packageSlug) => {
|
|
571
|
+
let packageJsonPath = path6.join(targetDir, "package.json");
|
|
572
|
+
if (fs4.existsSync(packageJsonPath)) {
|
|
573
|
+
let packageJson = JSON.parse(fs4.readFileSync(packageJsonPath, "utf-8"));
|
|
574
|
+
packageJson.name = packageSlug, fs4.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 4) + `
|
|
445
575
|
`);
|
|
576
|
+
}
|
|
577
|
+
};
|
|
578
|
+
|
|
579
|
+
// src/commands/create/utils/initTemplate.ts
|
|
580
|
+
var initTemplate = async ({ answers, targetDir }) => {
|
|
581
|
+
fs5.existsSync(targetDir) || fs5.mkdirSync(targetDir, { recursive: !0 });
|
|
582
|
+
let templatesBaseDir = getTemplatesBaseDir(), templatesDir = path7.join(templatesBaseDir, answers.template), sharedDir = path7.join(templatesBaseDir, "_shared");
|
|
583
|
+
await copyDirectory(sharedDir, targetDir), await copyDirectory(templatesDir, targetDir), updatePackageJson(targetDir, answers.packageSlug), logger_default.info("Created template with marketplace publication requirements."), logger_default.info(
|
|
584
|
+
"Before publishing, add ./marketplace/index.md, ./marketplace/header-image.jpg (784:325), and ./public/logo.svg (square)."
|
|
585
|
+
);
|
|
586
|
+
};
|
|
587
|
+
|
|
588
|
+
// src/commands/create/index.ts
|
|
589
|
+
var DEFAULT_VERSION = "0.0.1";
|
|
590
|
+
async function create() {
|
|
591
|
+
logger_default.info(getWelcomeMessage(process.cwd()));
|
|
592
|
+
let packageSlug = await (0, import_prompts2.input)({
|
|
593
|
+
message: "Enter app slug (e.g., my-tracker-plugin):",
|
|
594
|
+
required: !0
|
|
595
|
+
}), pluginName = await (0, import_prompts2.input)({
|
|
596
|
+
message: "Enter plugin name:",
|
|
597
|
+
required: !0
|
|
598
|
+
}), pluginDescription = await (0, import_prompts2.input)({
|
|
599
|
+
message: "Enter plugin description:",
|
|
600
|
+
required: !0
|
|
601
|
+
}), supportEmail = await (0, import_prompts2.input)({
|
|
602
|
+
message: "Enter support email:",
|
|
603
|
+
required: !0,
|
|
604
|
+
validate: (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value) || "Please enter a valid email address"
|
|
605
|
+
}), template = await (0, import_prompts2.select)({
|
|
606
|
+
message: "Select a template:",
|
|
607
|
+
choices: TEMPLATES.map((templateName) => ({
|
|
608
|
+
name: templateName,
|
|
609
|
+
value: templateName
|
|
610
|
+
}))
|
|
611
|
+
}), dataPermissions = await (0, import_prompts2.checkbox)({
|
|
612
|
+
message: "Select data permissions (some popular options):",
|
|
613
|
+
choices: TOP_DATA_PERMISSIONS.map((permission) => ({
|
|
614
|
+
name: permission,
|
|
615
|
+
value: permission
|
|
616
|
+
}))
|
|
617
|
+
}), answers = {
|
|
618
|
+
packageSlug,
|
|
619
|
+
slotTitle: packageSlug,
|
|
620
|
+
pluginName,
|
|
621
|
+
pluginDescription,
|
|
622
|
+
supportEmail,
|
|
623
|
+
template,
|
|
624
|
+
permissions: {
|
|
625
|
+
data: dataPermissions
|
|
626
|
+
},
|
|
627
|
+
version: DEFAULT_VERSION
|
|
628
|
+
}, targetDir = path8.join(process.cwd(), answers.packageSlug);
|
|
629
|
+
await initTemplate({
|
|
630
|
+
answers,
|
|
631
|
+
targetDir
|
|
632
|
+
}), initManifest({
|
|
633
|
+
answers,
|
|
634
|
+
targetDir
|
|
635
|
+
}), logger_default.newLine(), logger_default.success("Package generated!"), logger_default.commands("To get started, run", [
|
|
636
|
+
`cd ${answers.packageSlug}`,
|
|
637
|
+
"npm install",
|
|
638
|
+
"tracker-cli debug"
|
|
639
|
+
]);
|
|
446
640
|
}
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
summary: buildIssueSummary(slug),
|
|
451
|
-
description: buildIssueDescription({ pluginId, slug, version, manifestJson }),
|
|
452
|
-
tags: ["tracker-plugin"]
|
|
453
|
-
};
|
|
454
|
-
return trackerApiRequest("/issues", {
|
|
455
|
-
method: "POST",
|
|
456
|
-
body
|
|
457
|
-
});
|
|
458
|
-
}
|
|
459
|
-
async function updatePluginIssue(issueKey, params) {
|
|
460
|
-
return trackerApiRequest(`/issues/${issueKey}`, {
|
|
461
|
-
method: "PATCH",
|
|
462
|
-
body: params
|
|
463
|
-
});
|
|
464
|
-
}
|
|
465
|
-
async function attachFileToIssue(issueKey, fileBuffer, fileName) {
|
|
466
|
-
let formData = new import_form_data.default();
|
|
467
|
-
return formData.append("file", fileBuffer, {
|
|
468
|
-
filename: fileName,
|
|
469
|
-
contentType: "application/zip"
|
|
470
|
-
}), trackerApiRequest(`/issues/${issueKey}/attachments`, {
|
|
471
|
-
method: "POST",
|
|
472
|
-
formData
|
|
473
|
-
});
|
|
474
|
-
}
|
|
475
|
-
async function getIssueAttachments(issueKey) {
|
|
476
|
-
return trackerApiRequest(`/issues/${issueKey}/attachments`, {
|
|
477
|
-
method: "GET"
|
|
478
|
-
});
|
|
479
|
-
}
|
|
480
|
-
async function getIssueTransitions(issueKey) {
|
|
481
|
-
return trackerApiRequest(`/issues/${issueKey}/transitions`, {
|
|
482
|
-
method: "GET"
|
|
483
|
-
});
|
|
484
|
-
}
|
|
485
|
-
async function executeIssueTransition(issueKey, transitionId) {
|
|
486
|
-
await trackerApiRequest(`/issues/${issueKey}/transitions/${transitionId}/_execute`, {
|
|
487
|
-
method: "POST",
|
|
488
|
-
body: {}
|
|
489
|
-
});
|
|
490
|
-
}
|
|
491
|
-
async function getIssue(issueKey) {
|
|
492
|
-
return trackerApiRequest(`/issues/${issueKey}`, {
|
|
493
|
-
method: "GET"
|
|
494
|
-
});
|
|
495
|
-
}
|
|
496
|
-
async function getMyPluginIssues() {
|
|
497
|
-
return trackerApiRequest("/issues/_search", {
|
|
498
|
-
method: "POST",
|
|
499
|
-
body: {
|
|
500
|
-
filter: {
|
|
501
|
-
queue: PLUGINMOD_QUEUE,
|
|
502
|
-
createdBy: "me()"
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
});
|
|
506
|
-
}
|
|
507
|
-
async function addIssueComment(issueKey, text) {
|
|
508
|
-
await trackerApiRequest(`/issues/${issueKey}/comments`, {
|
|
509
|
-
method: "POST",
|
|
510
|
-
body: { text }
|
|
511
|
-
});
|
|
512
|
-
}
|
|
641
|
+
|
|
642
|
+
// src/commands/debug/index.ts
|
|
643
|
+
var import_fs7 = __toESM(require("fs")), import_path8 = __toESM(require("path"));
|
|
513
644
|
|
|
514
645
|
// src/core/manifest/manifestManager.ts
|
|
515
|
-
var
|
|
646
|
+
var import_fs3 = require("fs"), import_promises = require("fs/promises"), import_ajv = __toESM(require("ajv")), import_ajv_formats = __toESM(require("ajv-formats"));
|
|
516
647
|
|
|
517
648
|
// src/core/manifest/formatValidationErrors.ts
|
|
518
649
|
var priorityOrder = [
|
|
@@ -539,14 +670,14 @@ var priorityOrder = [
|
|
|
539
670
|
}, formatValidationErrors = (errors) => {
|
|
540
671
|
let errorsByPath = {};
|
|
541
672
|
for (let error2 of errors) {
|
|
542
|
-
let
|
|
543
|
-
errorsByPath[
|
|
673
|
+
let path18 = error2.instancePath || "root";
|
|
674
|
+
errorsByPath[path18] || (errorsByPath[path18] = []), errorsByPath[path18].push(error2);
|
|
544
675
|
}
|
|
545
|
-
return Object.entries(errorsByPath).map(([
|
|
676
|
+
return Object.entries(errorsByPath).map(([path18, pathErrors]) => {
|
|
546
677
|
let error2 = [...pathErrors].sort(
|
|
547
678
|
(a, b) => getPriority(a.keyword) - getPriority(b.keyword)
|
|
548
679
|
)[0], formatter = errorMessages[error2.keyword], message = formatter ? formatter(error2.params) : error2.message;
|
|
549
|
-
return ` - ${
|
|
680
|
+
return ` - ${path18}: ${message}`;
|
|
550
681
|
}).join(`
|
|
551
682
|
`);
|
|
552
683
|
};
|
|
@@ -560,7 +691,10 @@ var manifest_schema_default = {
|
|
|
560
691
|
required: [
|
|
561
692
|
"slug",
|
|
562
693
|
"version",
|
|
563
|
-
"permissions"
|
|
694
|
+
"permissions",
|
|
695
|
+
"name",
|
|
696
|
+
"description",
|
|
697
|
+
"support"
|
|
564
698
|
],
|
|
565
699
|
properties: {
|
|
566
700
|
$schema: {
|
|
@@ -573,6 +707,23 @@ var manifest_schema_default = {
|
|
|
573
707
|
maxLength: 63,
|
|
574
708
|
pattern: "^[a-z0-9-]+$"
|
|
575
709
|
},
|
|
710
|
+
manifest_version: {
|
|
711
|
+
type: "number",
|
|
712
|
+
description: "Manifest format version",
|
|
713
|
+
minimum: 1
|
|
714
|
+
},
|
|
715
|
+
supported_services: {
|
|
716
|
+
type: "array",
|
|
717
|
+
description: "Supported services for this plugin",
|
|
718
|
+
items: {
|
|
719
|
+
type: "string",
|
|
720
|
+
enum: [
|
|
721
|
+
"tracker"
|
|
722
|
+
]
|
|
723
|
+
},
|
|
724
|
+
minItems: 1,
|
|
725
|
+
uniqueItems: !0
|
|
726
|
+
},
|
|
576
727
|
slug: {
|
|
577
728
|
type: "string",
|
|
578
729
|
description: "Unique identifier for the plugin (lowercase letters, numbers, hyphen)",
|
|
@@ -621,13 +772,13 @@ var manifest_schema_default = {
|
|
|
621
772
|
type: "string",
|
|
622
773
|
description: "Russian description",
|
|
623
774
|
minLength: 1,
|
|
624
|
-
maxLength:
|
|
775
|
+
maxLength: 255
|
|
625
776
|
},
|
|
626
777
|
en: {
|
|
627
778
|
type: "string",
|
|
628
779
|
description: "English description",
|
|
629
780
|
minLength: 1,
|
|
630
|
-
maxLength:
|
|
781
|
+
maxLength: 255
|
|
631
782
|
}
|
|
632
783
|
},
|
|
633
784
|
additionalProperties: !1
|
|
@@ -931,435 +1082,116 @@ var manifest_schema_default = {
|
|
|
931
1082
|
description: "Configuration for a specific slot",
|
|
932
1083
|
required: [
|
|
933
1084
|
"entrypoint",
|
|
934
|
-
"title"
|
|
935
|
-
],
|
|
936
|
-
properties: {
|
|
937
|
-
entrypoint: {
|
|
938
|
-
type: "string",
|
|
939
|
-
description: "Entry point file path for the slot",
|
|
940
|
-
minLength: 1
|
|
941
|
-
},
|
|
942
|
-
title: {
|
|
943
|
-
type: "object",
|
|
944
|
-
description: "Localized titles for the slot",
|
|
945
|
-
required: [
|
|
946
|
-
"ru",
|
|
947
|
-
"en"
|
|
948
|
-
],
|
|
949
|
-
properties: {
|
|
950
|
-
ru: {
|
|
951
|
-
type: "string",
|
|
952
|
-
description: "Russian title",
|
|
953
|
-
minLength: 1,
|
|
954
|
-
maxLength: 32
|
|
955
|
-
},
|
|
956
|
-
en: {
|
|
957
|
-
type: "string",
|
|
958
|
-
description: "English title",
|
|
959
|
-
minLength: 1,
|
|
960
|
-
maxLength: 32
|
|
961
|
-
}
|
|
962
|
-
},
|
|
963
|
-
additionalProperties: !1
|
|
964
|
-
},
|
|
965
|
-
description: {
|
|
966
|
-
type: "object",
|
|
967
|
-
description: "Localized descriptions for the slot",
|
|
968
|
-
required: [
|
|
969
|
-
"ru",
|
|
970
|
-
"en"
|
|
971
|
-
],
|
|
972
|
-
properties: {
|
|
973
|
-
ru: {
|
|
974
|
-
type: "string",
|
|
975
|
-
description: "Russian description",
|
|
976
|
-
minLength: 1,
|
|
977
|
-
maxLength: 300
|
|
978
|
-
},
|
|
979
|
-
en: {
|
|
980
|
-
type: "string",
|
|
981
|
-
description: "English description",
|
|
982
|
-
minLength: 1,
|
|
983
|
-
maxLength: 300
|
|
984
|
-
}
|
|
985
|
-
},
|
|
986
|
-
additionalProperties: !1
|
|
987
|
-
}
|
|
988
|
-
},
|
|
989
|
-
additionalProperties: !1
|
|
990
|
-
}
|
|
991
|
-
}
|
|
992
|
-
};
|
|
993
|
-
|
|
994
|
-
// src/core/manifest/manifestManager.ts
|
|
995
|
-
var validator = (() => {
|
|
996
|
-
let ajv = new import_ajv.default({ allErrors: !0, strict: !1 });
|
|
997
|
-
return (0, import_ajv_formats.default)(ajv), ajv.compile(manifest_schema_default);
|
|
998
|
-
})(), manifestPath = "./manifest.json", parseManifest = (content) => {
|
|
999
|
-
let manifest;
|
|
1000
|
-
try {
|
|
1001
|
-
manifest = JSON.parse(content);
|
|
1002
|
-
} catch (error2) {
|
|
1003
|
-
throw error2 instanceof SyntaxError ? new Error(`File manifest.json contains invalid JSON: ${error2.message}`) : new Error(`Error reading manifest.json: ${error2.message}`);
|
|
1004
|
-
}
|
|
1005
|
-
return manifest;
|
|
1006
|
-
}, loadRaw = async () => {
|
|
1007
|
-
if (!(0, import_fs2.existsSync)(manifestPath))
|
|
1008
|
-
throw new Error(`File manifest.json not found at path: ${manifestPath}`);
|
|
1009
|
-
try {
|
|
1010
|
-
return await (0, import_promises2.readFile)(manifestPath, "utf8");
|
|
1011
|
-
} catch (error2) {
|
|
1012
|
-
throw error2 instanceof Error ? new Error(`Error reading manifest.json: ${error2.message}`) : new Error("Error loading manifest");
|
|
1013
|
-
}
|
|
1014
|
-
}, load = async () => {
|
|
1015
|
-
let manifestContent = await loadRaw();
|
|
1016
|
-
return parseManifest(manifestContent);
|
|
1017
|
-
}, validate = async () => {
|
|
1018
|
-
let manifest = await load();
|
|
1019
|
-
if (!validator(manifest) && validator.errors) {
|
|
1020
|
-
let errorMessages2 = formatValidationErrors(validator.errors);
|
|
1021
|
-
throw new Error(`Manifest validation failed:
|
|
1022
|
-
${errorMessages2}`);
|
|
1023
|
-
}
|
|
1024
|
-
}, save = async (manifest) => {
|
|
1025
|
-
try {
|
|
1026
|
-
let content = JSON.stringify(manifest, null, 4);
|
|
1027
|
-
await (0, import_promises2.writeFile)(manifestPath, content, "utf8");
|
|
1028
|
-
} catch (error2) {
|
|
1029
|
-
throw error2 instanceof Error ? new Error(`Error saving manifest.json: ${error2.message}`) : new Error("Error saving manifest");
|
|
1030
|
-
}
|
|
1031
|
-
}, update = async (updates) => {
|
|
1032
|
-
let updatedManifest = { ...await load(), ...updates };
|
|
1033
|
-
return await save(updatedManifest), updatedManifest;
|
|
1034
|
-
}, manifestManager = {
|
|
1035
|
-
load,
|
|
1036
|
-
loadRaw,
|
|
1037
|
-
validate,
|
|
1038
|
-
save,
|
|
1039
|
-
update
|
|
1040
|
-
};
|
|
1041
|
-
|
|
1042
|
-
// src/core/pluginState/pluginStateManager.ts
|
|
1043
|
-
var import_fs3 = require("fs"), import_promises3 = require("fs/promises"), STATE_FILE = ".tracker-plugin", load2 = async () => {
|
|
1044
|
-
if (!(0, import_fs3.existsSync)(STATE_FILE))
|
|
1045
|
-
return {};
|
|
1046
|
-
try {
|
|
1047
|
-
let content = await (0, import_promises3.readFile)(STATE_FILE, "utf8");
|
|
1048
|
-
return JSON.parse(content);
|
|
1049
|
-
} catch {
|
|
1050
|
-
return {};
|
|
1051
|
-
}
|
|
1052
|
-
}, save2 = async (state) => {
|
|
1053
|
-
try {
|
|
1054
|
-
let content = JSON.stringify(state, null, 4);
|
|
1055
|
-
await (0, import_promises3.writeFile)(STATE_FILE, content, "utf8");
|
|
1056
|
-
} catch (error2) {
|
|
1057
|
-
throw error2 instanceof Error ? new Error(`Error saving ${STATE_FILE}: ${error2.message}`) : new Error(`Error saving ${STATE_FILE}`);
|
|
1058
|
-
}
|
|
1059
|
-
}, update2 = async (updates) => {
|
|
1060
|
-
let updated = { ...await load2(), ...updates };
|
|
1061
|
-
return await save2(updated), updated;
|
|
1062
|
-
}, pluginStateManager = {
|
|
1063
|
-
load: load2,
|
|
1064
|
-
save: save2,
|
|
1065
|
-
update: update2
|
|
1066
|
-
};
|
|
1067
|
-
|
|
1068
|
-
// src/commands/catalog/index.ts
|
|
1069
|
-
init_logger();
|
|
1070
|
-
|
|
1071
|
-
// src/utils/promptPluginMetadata.ts
|
|
1072
|
-
var import_prompts2 = require("@inquirer/prompts");
|
|
1073
|
-
async function promptPluginName() {
|
|
1074
|
-
return (0, import_prompts2.input)({
|
|
1075
|
-
message: "Plugin name:",
|
|
1076
|
-
validate: (value) => value.trim() ? !0 : "Name is required"
|
|
1077
|
-
});
|
|
1078
|
-
}
|
|
1079
|
-
async function promptPluginDescription() {
|
|
1080
|
-
return (0, import_prompts2.input)({
|
|
1081
|
-
message: "Plugin description:",
|
|
1082
|
-
validate: (value) => value.trim() ? !0 : "Description is required"
|
|
1083
|
-
});
|
|
1084
|
-
}
|
|
1085
|
-
async function promptPluginId(manifest) {
|
|
1086
|
-
return (0, import_prompts2.input)({
|
|
1087
|
-
message: "Plugin ID:",
|
|
1088
|
-
default: manifest.id || void 0,
|
|
1089
|
-
validate: (value) => value.trim() ? !0 : "Plugin ID is required"
|
|
1090
|
-
});
|
|
1091
|
-
}
|
|
1092
|
-
async function promptPluginTags() {
|
|
1093
|
-
return (await (0, import_prompts2.input)({
|
|
1094
|
-
message: "Tags (comma-separated):"
|
|
1095
|
-
})).split(",").map((tag) => tag.trim()).filter((tag) => tag.length > 0);
|
|
1096
|
-
}
|
|
1097
|
-
|
|
1098
|
-
// src/commands/catalog/index.ts
|
|
1099
|
-
async function catalog() {
|
|
1100
|
-
let manifest = await manifestManager.load(), state = await pluginStateManager.load();
|
|
1101
|
-
if (!state.trackerIssueKey) {
|
|
1102
|
-
logger_default.warning('Plugin is not registered yet. Run "tracker-cli register" first.'), logger_default.suggest("tracker-cli register");
|
|
1103
|
-
return;
|
|
1104
|
-
}
|
|
1105
|
-
logger_default.newLine(), logger_default.info("\u{1F4DD} Catalog entry information:");
|
|
1106
|
-
let name = await promptPluginName(), description = await promptPluginDescription(), tags = await promptPluginTags();
|
|
1107
|
-
await pluginStateManager.update({
|
|
1108
|
-
catalog: { name, description, tags }
|
|
1109
|
-
}), logger_default.newLine(), logger_default.info("\u{1F4E4} Syncing catalog metadata to Tracker issue...");
|
|
1110
|
-
let manifestJson = await manifestManager.loadRaw(), issueDescription = buildIssueDescription({
|
|
1111
|
-
pluginId: manifest.id ?? "",
|
|
1112
|
-
slug: manifest.slug,
|
|
1113
|
-
version: manifest.version,
|
|
1114
|
-
manifestJson,
|
|
1115
|
-
catalogName: name,
|
|
1116
|
-
catalogDescription: description,
|
|
1117
|
-
catalogTags: tags
|
|
1118
|
-
});
|
|
1119
|
-
await updatePluginIssue(state.trackerIssueKey, {
|
|
1120
|
-
description: issueDescription
|
|
1121
|
-
}), logger_default.success("Catalog entry updated successfully!");
|
|
1122
|
-
}
|
|
1123
|
-
|
|
1124
|
-
// src/commands/create/index.ts
|
|
1125
|
-
var path8 = __toESM(require("path")), import_prompts3 = require("@inquirer/prompts");
|
|
1126
|
-
|
|
1127
|
-
// src/core/manifest/constants.ts
|
|
1128
|
-
var DATA_PERMISSIONS = [
|
|
1129
|
-
// top 10
|
|
1130
|
-
"tracker:issues:read",
|
|
1131
|
-
"tracker:issues:write",
|
|
1132
|
-
"tracker:issuetypes:read",
|
|
1133
|
-
"tracker:statuses:read",
|
|
1134
|
-
"tracker:queues:read",
|
|
1135
|
-
"tracker:fields:read",
|
|
1136
|
-
"tracker:entities:read",
|
|
1137
|
-
"tracker:attachments:read",
|
|
1138
|
-
"tracker:attachments:write",
|
|
1139
|
-
// in alphabetical order
|
|
1140
|
-
"tracker:applications:read",
|
|
1141
|
-
"tracker:boards:read",
|
|
1142
|
-
"tracker:boards:write",
|
|
1143
|
-
"tracker:bulk:read",
|
|
1144
|
-
"tracker:bulk:write",
|
|
1145
|
-
"tracker:bulkchange:read",
|
|
1146
|
-
"tracker:bulkchange:write",
|
|
1147
|
-
"tracker:charts:read",
|
|
1148
|
-
"tracker:commentTemplates:read",
|
|
1149
|
-
"tracker:commentTemplates:write",
|
|
1150
|
-
"tracker:components:read",
|
|
1151
|
-
"tracker:components:write",
|
|
1152
|
-
"tracker:data:read",
|
|
1153
|
-
"tracker:departments:read",
|
|
1154
|
-
"tracker:entities:write",
|
|
1155
|
-
"tracker:externalEventTypes:write",
|
|
1156
|
-
"tracker:externalEvents:write",
|
|
1157
|
-
"tracker:fields:write",
|
|
1158
|
-
"tracker:filterFolders:write",
|
|
1159
|
-
"tracker:filters:read",
|
|
1160
|
-
"tracker:filters:write",
|
|
1161
|
-
"tracker:goals:read",
|
|
1162
|
-
"tracker:goals:write",
|
|
1163
|
-
"tracker:groups:read",
|
|
1164
|
-
"tracker:issueTemplates:read",
|
|
1165
|
-
"tracker:issueTemplates:write",
|
|
1166
|
-
"tracker:links:read",
|
|
1167
|
-
"tracker:linktypes:read",
|
|
1168
|
-
"tracker:liveBoards:write",
|
|
1169
|
-
"tracker:localFields:read",
|
|
1170
|
-
"tracker:maillists:read",
|
|
1171
|
-
"tracker:maillists:write",
|
|
1172
|
-
"tracker:myself:read",
|
|
1173
|
-
"tracker:myself:write",
|
|
1174
|
-
"tracker:priorities:read",
|
|
1175
|
-
"tracker:queues:write",
|
|
1176
|
-
"tracker:reminders:read",
|
|
1177
|
-
"tracker:reminders:write",
|
|
1178
|
-
"tracker:remotelinks:read",
|
|
1179
|
-
"tracker:reports:read",
|
|
1180
|
-
"tracker:reports:write",
|
|
1181
|
-
"tracker:resolutions:read",
|
|
1182
|
-
"tracker:resources:read",
|
|
1183
|
-
"tracker:resources:write",
|
|
1184
|
-
"tracker:roles:read",
|
|
1185
|
-
"tracker:screens:read",
|
|
1186
|
-
"tracker:services:read",
|
|
1187
|
-
"tracker:sprints:read",
|
|
1188
|
-
"tracker:sprints:write",
|
|
1189
|
-
"tracker:system:write",
|
|
1190
|
-
"tracker:tags:read",
|
|
1191
|
-
"tracker:translations:read",
|
|
1192
|
-
"tracker:users:read",
|
|
1193
|
-
"tracker:users:write",
|
|
1194
|
-
"tracker:versions:read",
|
|
1195
|
-
"tracker:versions:write",
|
|
1196
|
-
"tracker:workflows:read",
|
|
1197
|
-
"tracker:workflows:write",
|
|
1198
|
-
"tracker:worklog:read",
|
|
1199
|
-
"tracker:worklog:write"
|
|
1200
|
-
], TOP_DATA_PERMISSIONS = DATA_PERMISSIONS.slice(0, 10);
|
|
1201
|
-
var TEMPLATES = [
|
|
1202
|
-
"default",
|
|
1203
|
-
"issue.action",
|
|
1204
|
-
"issue.block",
|
|
1205
|
-
"issue.tab",
|
|
1206
|
-
"issue.comment.action",
|
|
1207
|
-
"navigation",
|
|
1208
|
-
"trigger.action",
|
|
1209
|
-
"project.action",
|
|
1210
|
-
"portfolio.action",
|
|
1211
|
-
"goal.action",
|
|
1212
|
-
"issue.floatingbottom.action",
|
|
1213
|
-
"attachment.viewer.action"
|
|
1214
|
-
];
|
|
1215
|
-
var TEMPLATE_SLOTS = {
|
|
1216
|
-
default: [],
|
|
1217
|
-
"issue.action": ["issue.action"],
|
|
1218
|
-
"issue.block": ["issue.block"],
|
|
1219
|
-
"issue.tab": ["issue.tab"],
|
|
1220
|
-
"issue.comment.action": ["issue.comment.action"],
|
|
1221
|
-
navigation: ["navigation"],
|
|
1222
|
-
"trigger.action": ["trigger.create.action", "trigger.edit.action"],
|
|
1223
|
-
"project.action": ["project.action"],
|
|
1224
|
-
"portfolio.action": ["portfolio.action"],
|
|
1225
|
-
"goal.action": ["goal.action"],
|
|
1226
|
-
"issue.floatingbottom.action": ["issue.floatingbottom.action"],
|
|
1227
|
-
"attachment.viewer.action": ["attachment.viewer.action"]
|
|
1228
|
-
};
|
|
1229
|
-
|
|
1230
|
-
// src/commands/create/index.ts
|
|
1231
|
-
init_logger();
|
|
1232
|
-
|
|
1233
|
-
// src/commands/create/utils/getWelcomeMessage.ts
|
|
1234
|
-
var import_picocolors2 = __toESM(require("picocolors")), getWelcomeMessage = (pwd) => `
|
|
1235
|
-
${import_picocolors2.default.bold(import_picocolors2.default.white("\u{1F680} Create new tracker plugin"))}
|
|
1236
|
-
|
|
1237
|
-
${import_picocolors2.default.dim(`\u{1F4C1} Creating an app in your current directory: ${pwd}`)}
|
|
1238
|
-
|
|
1239
|
-
${import_picocolors2.default.dim("Press")} ${import_picocolors2.default.yellow("Ctrl+C")} ${import_picocolors2.default.dim("to cancel.")}
|
|
1240
|
-
`;
|
|
1241
|
-
|
|
1242
|
-
// src/commands/create/utils/initManifest.ts
|
|
1243
|
-
var fs2 = __toESM(require("fs")), path3 = __toESM(require("path"));
|
|
1244
|
-
|
|
1245
|
-
// src/commands/create/utils/generateManifest.ts
|
|
1246
|
-
function buildSlots(template, slotTitle) {
|
|
1247
|
-
let slotNames = TEMPLATE_SLOTS[template];
|
|
1248
|
-
if (slotNames.length === 0) return;
|
|
1249
|
-
let slotEntry = {
|
|
1250
|
-
entrypoint: "index.html",
|
|
1251
|
-
title: { ru: slotTitle, en: slotTitle }
|
|
1252
|
-
};
|
|
1253
|
-
return {
|
|
1254
|
-
tracker: Object.fromEntries(slotNames.map((slotName) => [slotName, [slotEntry]]))
|
|
1255
|
-
};
|
|
1256
|
-
}
|
|
1257
|
-
var generateManifest = (answers) => ({
|
|
1258
|
-
$schema: "./manifest.schema.json",
|
|
1259
|
-
slug: answers.packageSlug,
|
|
1260
|
-
version: answers.version,
|
|
1261
|
-
permissions: answers.permissions,
|
|
1262
|
-
slots: buildSlots(answers.template, answers.slotTitle)
|
|
1263
|
-
});
|
|
1264
|
-
|
|
1265
|
-
// src/commands/create/utils/initManifest.ts
|
|
1266
|
-
var initManifest = ({ answers, targetDir }) => {
|
|
1267
|
-
let generatedManifest = generateManifest(answers), manifestPath2 = path3.join(targetDir, "manifest.json");
|
|
1268
|
-
fs2.writeFileSync(manifestPath2, JSON.stringify(generatedManifest, null, 2), "utf-8");
|
|
1269
|
-
};
|
|
1270
|
-
|
|
1271
|
-
// src/commands/create/utils/initTemplate.ts
|
|
1272
|
-
var fs5 = __toESM(require("fs")), path7 = __toESM(require("path"));
|
|
1273
|
-
|
|
1274
|
-
// src/utils/copyDirectory.ts
|
|
1275
|
-
var fs3 = __toESM(require("fs")), import_path2 = __toESM(require("path")), import_tinyglobby = require("tinyglobby"), resolveTargetFileName = (file) => file.endsWith(".template") ? "." + file.replace(".template", "") : file, copyDirectory = async (sourceDir, targetDir) => {
|
|
1276
|
-
let files = await (0, import_tinyglobby.glob)(["**/*"], {
|
|
1277
|
-
cwd: sourceDir,
|
|
1278
|
-
onlyFiles: !0,
|
|
1279
|
-
dot: !0
|
|
1280
|
-
});
|
|
1281
|
-
await Promise.all(
|
|
1282
|
-
files.map(async (file) => {
|
|
1283
|
-
let sourcePath = import_path2.default.join(sourceDir, file), targetFile = resolveTargetFileName(file), targetPath = import_path2.default.join(targetDir, targetFile);
|
|
1284
|
-
await fs3.promises.mkdir(import_path2.default.dirname(targetPath), { recursive: !0 }), await fs3.promises.copyFile(sourcePath, targetPath);
|
|
1285
|
-
})
|
|
1286
|
-
);
|
|
1287
|
-
};
|
|
1288
|
-
|
|
1289
|
-
// src/utils/getProjectPath.ts
|
|
1290
|
-
var import_path3 = __toESM(require("path")), isDevelopment = () => __dirname.includes("/src/"), getProjectPath = (relativePath) => {
|
|
1291
|
-
let levelsUp = isDevelopment() ? "../.." : "..";
|
|
1292
|
-
return import_path3.default.resolve(__dirname, levelsUp, relativePath);
|
|
1293
|
-
}, getTemplatesBaseDir = () => getProjectPath("templates"), getTemplatePath = (filename) => import_path3.default.join(getTemplatesBaseDir(), "_shared", filename);
|
|
1294
|
-
|
|
1295
|
-
// src/commands/create/utils/initTemplate.ts
|
|
1296
|
-
init_logger();
|
|
1297
|
-
|
|
1298
|
-
// src/commands/create/utils/updatePackageJson.ts
|
|
1299
|
-
var fs4 = __toESM(require("fs")), path6 = __toESM(require("path")), updatePackageJson = (targetDir, packageSlug) => {
|
|
1300
|
-
let packageJsonPath = path6.join(targetDir, "package.json");
|
|
1301
|
-
if (fs4.existsSync(packageJsonPath)) {
|
|
1302
|
-
let packageJson = JSON.parse(fs4.readFileSync(packageJsonPath, "utf-8"));
|
|
1303
|
-
packageJson.name = packageSlug, fs4.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 4) + `
|
|
1304
|
-
`);
|
|
1085
|
+
"title"
|
|
1086
|
+
],
|
|
1087
|
+
properties: {
|
|
1088
|
+
entrypoint: {
|
|
1089
|
+
type: "string",
|
|
1090
|
+
description: "Entry point file path for the slot",
|
|
1091
|
+
minLength: 1
|
|
1092
|
+
},
|
|
1093
|
+
title: {
|
|
1094
|
+
type: "object",
|
|
1095
|
+
description: "Localized titles for the slot",
|
|
1096
|
+
required: [
|
|
1097
|
+
"ru",
|
|
1098
|
+
"en"
|
|
1099
|
+
],
|
|
1100
|
+
properties: {
|
|
1101
|
+
ru: {
|
|
1102
|
+
type: "string",
|
|
1103
|
+
description: "Russian title",
|
|
1104
|
+
minLength: 1,
|
|
1105
|
+
maxLength: 32
|
|
1106
|
+
},
|
|
1107
|
+
en: {
|
|
1108
|
+
type: "string",
|
|
1109
|
+
description: "English title",
|
|
1110
|
+
minLength: 1,
|
|
1111
|
+
maxLength: 32
|
|
1112
|
+
}
|
|
1113
|
+
},
|
|
1114
|
+
additionalProperties: !1
|
|
1115
|
+
},
|
|
1116
|
+
description: {
|
|
1117
|
+
type: "object",
|
|
1118
|
+
description: "Localized descriptions for the slot",
|
|
1119
|
+
required: [
|
|
1120
|
+
"ru",
|
|
1121
|
+
"en"
|
|
1122
|
+
],
|
|
1123
|
+
properties: {
|
|
1124
|
+
ru: {
|
|
1125
|
+
type: "string",
|
|
1126
|
+
description: "Russian description",
|
|
1127
|
+
minLength: 1,
|
|
1128
|
+
maxLength: 300
|
|
1129
|
+
},
|
|
1130
|
+
en: {
|
|
1131
|
+
type: "string",
|
|
1132
|
+
description: "English description",
|
|
1133
|
+
minLength: 1,
|
|
1134
|
+
maxLength: 300
|
|
1135
|
+
}
|
|
1136
|
+
},
|
|
1137
|
+
additionalProperties: !1
|
|
1138
|
+
}
|
|
1139
|
+
},
|
|
1140
|
+
additionalProperties: !1
|
|
1141
|
+
}
|
|
1305
1142
|
}
|
|
1306
1143
|
};
|
|
1307
1144
|
|
|
1308
|
-
// src/
|
|
1309
|
-
var
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1145
|
+
// src/core/manifest/manifestManager.ts
|
|
1146
|
+
var validator = (() => {
|
|
1147
|
+
let ajv = new import_ajv.default({ allErrors: !0, strict: !1 });
|
|
1148
|
+
return (0, import_ajv_formats.default)(ajv), ajv.compile(manifest_schema_default);
|
|
1149
|
+
})(), manifestPath = "./manifest.json", parseManifest = (content) => {
|
|
1150
|
+
let manifest;
|
|
1151
|
+
try {
|
|
1152
|
+
manifest = JSON.parse(content);
|
|
1153
|
+
} catch (error2) {
|
|
1154
|
+
throw error2 instanceof SyntaxError ? new Error(`File manifest.json contains invalid JSON: ${error2.message}`) : new Error(`Error reading manifest.json: ${error2.message}`);
|
|
1155
|
+
}
|
|
1156
|
+
return manifest;
|
|
1157
|
+
}, loadRaw = async () => {
|
|
1158
|
+
if (!(0, import_fs3.existsSync)(manifestPath))
|
|
1159
|
+
throw new Error(`File manifest.json not found at path: ${manifestPath}`);
|
|
1160
|
+
try {
|
|
1161
|
+
return await (0, import_promises.readFile)(manifestPath, "utf8");
|
|
1162
|
+
} catch (error2) {
|
|
1163
|
+
throw error2 instanceof Error ? new Error(`Error reading manifest.json: ${error2.message}`) : new Error("Error loading manifest");
|
|
1164
|
+
}
|
|
1165
|
+
}, load = async () => {
|
|
1166
|
+
let manifestContent = await loadRaw();
|
|
1167
|
+
return parseManifest(manifestContent);
|
|
1168
|
+
}, validate = async () => {
|
|
1169
|
+
let manifest = await load();
|
|
1170
|
+
if (!validator(manifest) && validator.errors) {
|
|
1171
|
+
let errorMessages2 = formatValidationErrors(validator.errors);
|
|
1172
|
+
throw new Error(`Manifest validation failed:
|
|
1173
|
+
${errorMessages2}`);
|
|
1174
|
+
}
|
|
1175
|
+
}, save = async (manifest) => {
|
|
1176
|
+
try {
|
|
1177
|
+
let content = JSON.stringify(manifest, null, 4);
|
|
1178
|
+
await (0, import_promises.writeFile)(manifestPath, content, "utf8");
|
|
1179
|
+
} catch (error2) {
|
|
1180
|
+
throw error2 instanceof Error ? new Error(`Error saving manifest.json: ${error2.message}`) : new Error("Error saving manifest");
|
|
1181
|
+
}
|
|
1182
|
+
}, update = async (updates) => {
|
|
1183
|
+
let updatedManifest = { ...await load(), ...updates };
|
|
1184
|
+
return await save(updatedManifest), updatedManifest;
|
|
1185
|
+
}, manifestManager = {
|
|
1186
|
+
load,
|
|
1187
|
+
loadRaw,
|
|
1188
|
+
validate,
|
|
1189
|
+
save,
|
|
1190
|
+
update
|
|
1315
1191
|
};
|
|
1316
1192
|
|
|
1317
|
-
// src/commands/create/index.ts
|
|
1318
|
-
var DEFAULT_VERSION = "0.0.1";
|
|
1319
|
-
async function create() {
|
|
1320
|
-
logger_default.info(getWelcomeMessage(process.cwd()));
|
|
1321
|
-
let packageSlug = await (0, import_prompts3.input)({
|
|
1322
|
-
message: "Enter app slug (e.g., my-tracker-plugin):",
|
|
1323
|
-
required: !0
|
|
1324
|
-
}), template = await (0, import_prompts3.select)({
|
|
1325
|
-
message: "Select a template:",
|
|
1326
|
-
choices: TEMPLATES.map((templateName) => ({
|
|
1327
|
-
name: templateName,
|
|
1328
|
-
value: templateName
|
|
1329
|
-
}))
|
|
1330
|
-
}), dataPermissions = await (0, import_prompts3.checkbox)({
|
|
1331
|
-
message: "Select data permissions (some popular options):",
|
|
1332
|
-
choices: TOP_DATA_PERMISSIONS.map((permission) => ({
|
|
1333
|
-
name: permission,
|
|
1334
|
-
value: permission
|
|
1335
|
-
}))
|
|
1336
|
-
}), answers = {
|
|
1337
|
-
packageSlug,
|
|
1338
|
-
slotTitle: packageSlug,
|
|
1339
|
-
template,
|
|
1340
|
-
permissions: {
|
|
1341
|
-
data: dataPermissions
|
|
1342
|
-
},
|
|
1343
|
-
version: DEFAULT_VERSION
|
|
1344
|
-
}, targetDir = path8.join(process.cwd(), answers.packageSlug);
|
|
1345
|
-
await initTemplate({
|
|
1346
|
-
answers,
|
|
1347
|
-
targetDir
|
|
1348
|
-
}), initManifest({
|
|
1349
|
-
answers,
|
|
1350
|
-
targetDir
|
|
1351
|
-
}), logger_default.newLine(), logger_default.success("Package generated!"), logger_default.commands("To get started, run", [
|
|
1352
|
-
`cd ${answers.packageSlug}`,
|
|
1353
|
-
"npm install",
|
|
1354
|
-
"tracker-cli debug"
|
|
1355
|
-
]);
|
|
1356
|
-
}
|
|
1357
|
-
|
|
1358
|
-
// src/commands/debug/index.ts
|
|
1359
|
-
var import_fs7 = __toESM(require("fs")), import_path7 = __toESM(require("path"));
|
|
1360
|
-
|
|
1361
1193
|
// src/core/s3config/constants.ts
|
|
1362
|
-
var CONFIG_FILE_NAME = "config.json", mimeTypes = {
|
|
1194
|
+
var CONFIG_FILE_NAME = "config.json", DEFAULT_ENVIRONMENT = "production", mimeTypes = {
|
|
1363
1195
|
".html": "text/html",
|
|
1364
1196
|
".css": "text/css",
|
|
1365
1197
|
".js": "text/javascript",
|
|
@@ -1390,13 +1222,13 @@ var registerCleanup = (cleanup) => {
|
|
|
1390
1222
|
};
|
|
1391
1223
|
|
|
1392
1224
|
// src/commands/debug/utils/createDebugConfig.ts
|
|
1393
|
-
var import_fs4 = __toESM(require("fs")),
|
|
1225
|
+
var import_fs4 = __toESM(require("fs")), import_path5 = __toESM(require("path"));
|
|
1394
1226
|
|
|
1395
1227
|
// src/utils/convertManifestToConfig.ts
|
|
1396
|
-
function buildPluginDownloadUrl(
|
|
1397
|
-
return `${
|
|
1228
|
+
function buildPluginDownloadUrl(env, id, version) {
|
|
1229
|
+
return `${getPluginDownloadBase2(env)}/${id}/${version}`;
|
|
1398
1230
|
}
|
|
1399
|
-
var convertManifestToConfig = (manifest,
|
|
1231
|
+
var convertManifestToConfig = (manifest, environment) => {
|
|
1400
1232
|
let config = {};
|
|
1401
1233
|
if (!manifest.slots)
|
|
1402
1234
|
return config;
|
|
@@ -1420,7 +1252,7 @@ var convertManifestToConfig = (manifest, downloadBaseUrl) => {
|
|
|
1420
1252
|
entrypoint: slotConfig.entrypoint,
|
|
1421
1253
|
title: slotConfig.title,
|
|
1422
1254
|
downloadUrl: buildPluginDownloadUrl(
|
|
1423
|
-
|
|
1255
|
+
environment,
|
|
1424
1256
|
manifest.slug,
|
|
1425
1257
|
manifest.version
|
|
1426
1258
|
)
|
|
@@ -1434,13 +1266,13 @@ var convertManifestToConfig = (manifest, downloadBaseUrl) => {
|
|
|
1434
1266
|
};
|
|
1435
1267
|
|
|
1436
1268
|
// src/commands/debug/utils/createDebugConfig.ts
|
|
1437
|
-
var
|
|
1438
|
-
let manifest = await manifestManager.load(), config = convertManifestToConfig(manifest,
|
|
1269
|
+
var createDebugConfig = async () => {
|
|
1270
|
+
let manifest = await manifestManager.load(), config = convertManifestToConfig(manifest, "debug"), configPath = import_path5.default.join(process.cwd(), CONFIG_FILE_NAME);
|
|
1439
1271
|
import_fs4.default.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
1440
1272
|
};
|
|
1441
1273
|
|
|
1442
1274
|
// src/commands/debug/utils/lockFile.ts
|
|
1443
|
-
var import_fs5 = __toESM(require("fs")),
|
|
1275
|
+
var import_fs5 = __toESM(require("fs")), import_path6 = __toESM(require("path")), LOCK_FILE_NAME = ".tracker-cli-debug.lock", getLockFilePath = () => import_path6.default.join(process.cwd(), LOCK_FILE_NAME), getRunningDebugPid = () => {
|
|
1444
1276
|
let lockPath = getLockFilePath();
|
|
1445
1277
|
if (!import_fs5.default.existsSync(lockPath))
|
|
1446
1278
|
return null;
|
|
@@ -1465,10 +1297,10 @@ var import_fs5 = __toESM(require("fs")), import_path5 = __toESM(require("path"))
|
|
|
1465
1297
|
};
|
|
1466
1298
|
|
|
1467
1299
|
// src/commands/debug/utils/watchManifest.ts
|
|
1468
|
-
var import_fs6 = __toESM(require("fs")),
|
|
1300
|
+
var import_fs6 = __toESM(require("fs")), import_path7 = __toESM(require("path"));
|
|
1469
1301
|
init_logger();
|
|
1470
1302
|
var watchManifest = () => {
|
|
1471
|
-
let manifestPath2 =
|
|
1303
|
+
let manifestPath2 = import_path7.default.join(process.cwd(), "manifest.json"), debounceTimer = null, watcher = import_fs6.default.watch(manifestPath2, async (eventType) => {
|
|
1472
1304
|
eventType === "change" && (debounceTimer && clearTimeout(debounceTimer), debounceTimer = setTimeout(async () => {
|
|
1473
1305
|
try {
|
|
1474
1306
|
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");
|
|
@@ -1492,7 +1324,7 @@ Please stop the existing instance before starting a new one.
|
|
|
1492
1324
|
If you lost the terminal tab, you can kill the process with:
|
|
1493
1325
|
kill ${runningPid}`
|
|
1494
1326
|
), process.exit(1));
|
|
1495
|
-
let configPath =
|
|
1327
|
+
let configPath = import_path8.default.join(process.cwd(), CONFIG_FILE_NAME);
|
|
1496
1328
|
options.lint && await manifestManager.validate(), await createDebugConfig();
|
|
1497
1329
|
let watcher = watchManifest(), cleanup = () => {
|
|
1498
1330
|
watcher.close(), import_fs7.default.existsSync(configPath) && import_fs7.default.unlinkSync(configPath), removeLockFile();
|
|
@@ -1500,16 +1332,21 @@ If you lost the terminal tab, you can kill the process with:
|
|
|
1500
1332
|
registerCleanup(cleanup), createLockFile(), await execCommand(pluginCmd.dev), cleanup();
|
|
1501
1333
|
}
|
|
1502
1334
|
|
|
1503
|
-
// src/
|
|
1504
|
-
var
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1335
|
+
// src/core/s3config/promptEnvironment.ts
|
|
1336
|
+
var import_prompts3 = require("@inquirer/prompts");
|
|
1337
|
+
async function promptEnvironment() {
|
|
1338
|
+
return await (0, import_prompts3.select)({
|
|
1339
|
+
message: "Select environment:",
|
|
1340
|
+
choices: [
|
|
1341
|
+
{ name: "Testing", value: "testing" },
|
|
1342
|
+
{ name: "Production", value: "production" }
|
|
1343
|
+
],
|
|
1344
|
+
default: "testing"
|
|
1345
|
+
});
|
|
1346
|
+
}
|
|
1511
1347
|
|
|
1512
1348
|
// src/core/s3config/s3Manager.ts
|
|
1349
|
+
var import_fs8 = require("fs"), import_promises2 = require("fs/promises"), os2 = __toESM(require("os")), import_path9 = __toESM(require("path")), import_client_s3 = require("@aws-sdk/client-s3"), import_lib_storage = require("@aws-sdk/lib-storage"), import_tinyglobby2 = require("tinyglobby");
|
|
1513
1350
|
init_logger();
|
|
1514
1351
|
|
|
1515
1352
|
// src/core/s3config/promptCredentials.ts
|
|
@@ -1540,23 +1377,22 @@ var import_prompts4 = require("@inquirer/prompts"), promptS3Credentials = async
|
|
|
1540
1377
|
};
|
|
1541
1378
|
|
|
1542
1379
|
// src/core/s3config/s3Manager.ts
|
|
1380
|
+
async function streamToBuffer(body) {
|
|
1381
|
+
if (!body)
|
|
1382
|
+
return Buffer.alloc(0);
|
|
1383
|
+
let chunks = [];
|
|
1384
|
+
for await (let chunk of body)
|
|
1385
|
+
chunks.push(Buffer.from(chunk));
|
|
1386
|
+
return Buffer.concat(chunks);
|
|
1387
|
+
}
|
|
1543
1388
|
var S3Manager = class {
|
|
1544
1389
|
constructor() {
|
|
1545
|
-
this.credentialsDir =
|
|
1546
|
-
this.credentialsFile =
|
|
1547
|
-
this._environment =
|
|
1548
|
-
this._settings = null;
|
|
1549
|
-
}
|
|
1550
|
-
async setEnvironment(environment) {
|
|
1551
|
-
this._environment = environment, this._settings = await getStorageSettings2(environment), logger_default.info(`Environment set to: ${environment}`);
|
|
1552
|
-
}
|
|
1553
|
-
getEnvironment() {
|
|
1554
|
-
return this._environment;
|
|
1390
|
+
this.credentialsDir = import_path9.default.join(os2.homedir(), ".tracker-cli");
|
|
1391
|
+
this.credentialsFile = import_path9.default.join(this.credentialsDir, "s3-credentials.json");
|
|
1392
|
+
this._environment = DEFAULT_ENVIRONMENT;
|
|
1555
1393
|
}
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
throw new Error("Storage settings not loaded. Call s3Manager.setEnvironment() first.");
|
|
1559
|
-
return this._settings;
|
|
1394
|
+
setEnvironment(environment) {
|
|
1395
|
+
this._environment = environment, logger_default.info(`Environment set to: ${environment}`);
|
|
1560
1396
|
}
|
|
1561
1397
|
async checkS3Auth() {
|
|
1562
1398
|
await this.checkAuth("s3");
|
|
@@ -1565,7 +1401,7 @@ var S3Manager = class {
|
|
|
1565
1401
|
await this.checkAuth("mds");
|
|
1566
1402
|
}
|
|
1567
1403
|
async saveCredentials(credentials) {
|
|
1568
|
-
(0, import_fs8.existsSync)(this.credentialsDir) || (0, import_fs8.mkdirSync)(this.credentialsDir, { recursive: !0, mode: 448 }), await (0,
|
|
1404
|
+
(0, import_fs8.existsSync)(this.credentialsDir) || (0, import_fs8.mkdirSync)(this.credentialsDir, { recursive: !0, mode: 448 }), await (0, import_promises2.writeFile)(this.credentialsFile, JSON.stringify(credentials, null, 2), {
|
|
1569
1405
|
mode: 384
|
|
1570
1406
|
});
|
|
1571
1407
|
}
|
|
@@ -1580,21 +1416,18 @@ var S3Manager = class {
|
|
|
1580
1416
|
}
|
|
1581
1417
|
}
|
|
1582
1418
|
async getPluginsConfig() {
|
|
1583
|
-
let s3Client = this.createMdsS3Client(), bucket = this.
|
|
1419
|
+
let s3Client = this.createMdsS3Client(), bucket = this.getConfigBucket();
|
|
1584
1420
|
try {
|
|
1585
|
-
let
|
|
1421
|
+
let response = await s3Client.send(
|
|
1586
1422
|
new import_client_s3.GetObjectCommand({ Bucket: bucket, Key: CONFIG_FILE_NAME })
|
|
1587
|
-
);
|
|
1588
|
-
|
|
1589
|
-
return logger_default.info("NO DATA"), {};
|
|
1590
|
-
let text = await Body.transformToString("utf8");
|
|
1591
|
-
return JSON.parse(text);
|
|
1423
|
+
), body = await streamToBuffer(response.Body);
|
|
1424
|
+
return body.length ? JSON.parse(body.toString("utf8")) : (logger_default.info("NO DATA"), {});
|
|
1592
1425
|
} catch (error2) {
|
|
1593
1426
|
return logger_default.error("Error getting plugins config from S3", error2), process.exit();
|
|
1594
1427
|
}
|
|
1595
1428
|
}
|
|
1596
1429
|
async savePluginsConfig(config) {
|
|
1597
|
-
let s3Client = this.createMdsS3Client(), bucket = this.
|
|
1430
|
+
let s3Client = this.createMdsS3Client(), bucket = this.getConfigBucket();
|
|
1598
1431
|
try {
|
|
1599
1432
|
await new import_lib_storage.Upload({
|
|
1600
1433
|
client: s3Client,
|
|
@@ -1614,11 +1447,11 @@ var S3Manager = class {
|
|
|
1614
1447
|
logger_default.warning("No files to upload in dist folder");
|
|
1615
1448
|
return;
|
|
1616
1449
|
}
|
|
1617
|
-
let keyPrefix = `${manifest.slug}/${manifest.version}/`, s3Client = this.createAwsS3Client(), distPath =
|
|
1450
|
+
let keyPrefix = `${manifest.slug}/${manifest.version}/`, s3Client = this.createAwsS3Client(), distPath = import_path9.default.resolve("./dist"), bucket = this.getStaticBucket();
|
|
1618
1451
|
logger_default.info(`\u{1F4E6} Starting file upload from ${distPath} to S3 bucket: ${bucket}`);
|
|
1619
1452
|
for (let filePath of files)
|
|
1620
1453
|
try {
|
|
1621
|
-
let fileContent = await (0,
|
|
1454
|
+
let fileContent = await (0, import_promises2.readFile)(filePath), relativePath = import_path9.default.relative(distPath, filePath), s3Key = keyPrefix + relativePath.replace(/\\/g, "/"), mimeType = this.getMimeType(filePath);
|
|
1622
1455
|
logger_default.info(`\u2B06\uFE0F Uploading: ${relativePath}`), await new import_lib_storage.Upload({
|
|
1623
1456
|
client: s3Client,
|
|
1624
1457
|
params: {
|
|
@@ -1639,15 +1472,15 @@ var S3Manager = class {
|
|
|
1639
1472
|
* @param rootPaths paths relative to cwd, e.g. ['manifest.json', 'marketplace']
|
|
1640
1473
|
*/
|
|
1641
1474
|
async uploadRootFiles(manifest, rootPaths) {
|
|
1642
|
-
let keyPrefix = `${manifest.slug}/${manifest.version}/`, s3Client = this.createAwsS3Client(), bucket = this.
|
|
1475
|
+
let keyPrefix = `${manifest.slug}/${manifest.version}/`, s3Client = this.createAwsS3Client(), bucket = this.getStaticBucket(), cwd = process.cwd();
|
|
1643
1476
|
for (let rootPath of rootPaths) {
|
|
1644
|
-
let absPath =
|
|
1477
|
+
let absPath = import_path9.default.resolve(cwd, rootPath);
|
|
1645
1478
|
if (!(0, import_fs8.existsSync)(absPath)) {
|
|
1646
1479
|
logger_default.warning(`Skipping "${rootPath}" \u2014 not found`);
|
|
1647
1480
|
continue;
|
|
1648
1481
|
}
|
|
1649
1482
|
if ((await import("fs")).statSync(absPath).isFile()) {
|
|
1650
|
-
let fileContent = await (0,
|
|
1483
|
+
let fileContent = await (0, import_promises2.readFile)(absPath), s3Key = keyPrefix + import_path9.default.basename(absPath), mimeType = this.getMimeType(absPath);
|
|
1651
1484
|
logger_default.info(`\u2B06\uFE0F Uploading: ${rootPath}`), await new import_lib_storage.Upload({
|
|
1652
1485
|
client: s3Client,
|
|
1653
1486
|
params: {
|
|
@@ -1665,7 +1498,7 @@ var S3Manager = class {
|
|
|
1665
1498
|
});
|
|
1666
1499
|
for (let filePath of files)
|
|
1667
1500
|
try {
|
|
1668
|
-
let fileContent = await (0,
|
|
1501
|
+
let fileContent = await (0, import_promises2.readFile)(filePath), relativePath = import_path9.default.relative(cwd, filePath), s3Key = keyPrefix + relativePath.replace(/\\/g, "/"), mimeType = this.getMimeType(filePath);
|
|
1669
1502
|
logger_default.info(`\u2B06\uFE0F Uploading: ${relativePath}`), await new import_lib_storage.Upload({
|
|
1670
1503
|
client: s3Client,
|
|
1671
1504
|
params: {
|
|
@@ -1682,10 +1515,10 @@ var S3Manager = class {
|
|
|
1682
1515
|
}
|
|
1683
1516
|
}
|
|
1684
1517
|
createAwsS3Client() {
|
|
1685
|
-
let credentials = this.credentials
|
|
1518
|
+
let credentials = this.credentials;
|
|
1686
1519
|
return (!credentials?.s3AccessKeyId || !credentials?.s3SecretAccessKey) && (logger_default.error("S3 credentials not found. Please log in using: tracker-cli login"), process.exit()), new import_client_s3.S3Client({
|
|
1687
|
-
region:
|
|
1688
|
-
endpoint:
|
|
1520
|
+
region: getS3Region2(),
|
|
1521
|
+
endpoint: getS3Endpoint2(),
|
|
1689
1522
|
credentials: {
|
|
1690
1523
|
accessKeyId: credentials.s3AccessKeyId,
|
|
1691
1524
|
secretAccessKey: credentials.s3SecretAccessKey
|
|
@@ -1700,10 +1533,9 @@ var S3Manager = class {
|
|
|
1700
1533
|
if (!creds || !creds.s3AccessKeyId || !creds.s3SecretAccessKey)
|
|
1701
1534
|
return !1;
|
|
1702
1535
|
try {
|
|
1703
|
-
let settings = await this.resolveSettings();
|
|
1704
1536
|
return await new import_client_s3.S3Client({
|
|
1705
|
-
region:
|
|
1706
|
-
endpoint:
|
|
1537
|
+
region: getS3Region2(),
|
|
1538
|
+
endpoint: getS3Endpoint2(),
|
|
1707
1539
|
credentials: {
|
|
1708
1540
|
accessKeyId: creds.s3AccessKeyId,
|
|
1709
1541
|
secretAccessKey: creds.s3SecretAccessKey
|
|
@@ -1718,18 +1550,8 @@ var S3Manager = class {
|
|
|
1718
1550
|
if (!creds || !creds.mdsAccessKeyId || !creds.mdsSecretAccessKey)
|
|
1719
1551
|
return !1;
|
|
1720
1552
|
try {
|
|
1721
|
-
let
|
|
1722
|
-
return await new import_client_s3.
|
|
1723
|
-
region: settings.awsRegion,
|
|
1724
|
-
endpoint: settings.mdsEndpoint,
|
|
1725
|
-
forcePathStyle: !0,
|
|
1726
|
-
credentials: {
|
|
1727
|
-
accessKeyId: creds.mdsAccessKeyId,
|
|
1728
|
-
secretAccessKey: creds.mdsSecretAccessKey
|
|
1729
|
-
}
|
|
1730
|
-
}).send(
|
|
1731
|
-
new import_client_s3.GetObjectCommand({ Bucket: settings.configBucket, Key: CONFIG_FILE_NAME })
|
|
1732
|
-
), !0;
|
|
1553
|
+
let mdsClient = this.buildMdsS3Client(creds), bucket = this.getConfigBucket();
|
|
1554
|
+
return await mdsClient.send(new import_client_s3.GetObjectCommand({ Bucket: bucket, Key: CONFIG_FILE_NAME })), !0;
|
|
1733
1555
|
} catch (error2) {
|
|
1734
1556
|
return logger_default.error("MDS credential validation failed:", error2), !1;
|
|
1735
1557
|
}
|
|
@@ -1760,11 +1582,20 @@ var S3Manager = class {
|
|
|
1760
1582
|
}
|
|
1761
1583
|
await this.saveCredentials(updatedCreds), logger_default.success(`${type.toUpperCase()} credentials saved successfully.`);
|
|
1762
1584
|
}
|
|
1585
|
+
getConfigBucket() {
|
|
1586
|
+
return getBuckets2()[this._environment].config;
|
|
1587
|
+
}
|
|
1588
|
+
getStaticBucket() {
|
|
1589
|
+
return getBuckets2()[this._environment].static;
|
|
1590
|
+
}
|
|
1763
1591
|
createMdsS3Client() {
|
|
1764
|
-
let credentials = this.credentials
|
|
1765
|
-
return (!credentials?.mdsAccessKeyId || !credentials?.mdsSecretAccessKey) && (logger_default.error("MdsS3 credentials not found. Please log in using: tracker-cli login"), process.exit()),
|
|
1766
|
-
|
|
1767
|
-
|
|
1592
|
+
let credentials = this.credentials;
|
|
1593
|
+
return (!credentials?.mdsAccessKeyId || !credentials?.mdsSecretAccessKey) && (logger_default.error("MdsS3 credentials not found. Please log in using: tracker-cli login"), process.exit()), this.buildMdsS3Client(credentials);
|
|
1594
|
+
}
|
|
1595
|
+
buildMdsS3Client(credentials) {
|
|
1596
|
+
return new import_client_s3.S3Client({
|
|
1597
|
+
region: getS3Region2(),
|
|
1598
|
+
endpoint: getMdsEndpoint2(),
|
|
1768
1599
|
forcePathStyle: !0,
|
|
1769
1600
|
credentials: {
|
|
1770
1601
|
accessKeyId: credentials.mdsAccessKeyId,
|
|
@@ -1772,37 +1603,192 @@ var S3Manager = class {
|
|
|
1772
1603
|
}
|
|
1773
1604
|
});
|
|
1774
1605
|
}
|
|
1775
|
-
async resolveSettings() {
|
|
1776
|
-
return this._settings ? this._settings : (this._settings = await getStorageSettings2(this._environment), this._settings);
|
|
1777
|
-
}
|
|
1778
1606
|
getMimeType(filePath) {
|
|
1779
|
-
let ext =
|
|
1607
|
+
let ext = import_path9.default.extname(filePath).toLowerCase();
|
|
1780
1608
|
return mimeTypes[ext] || "application/octet-stream";
|
|
1781
1609
|
}
|
|
1782
1610
|
}, s3Manager = new S3Manager();
|
|
1783
1611
|
|
|
1784
|
-
// src/utils/getFiles.ts
|
|
1785
|
-
var import_fs9 = __toESM(require("fs")),
|
|
1786
|
-
init_logger();
|
|
1787
|
-
var getFiles = async () => {
|
|
1788
|
-
let distPath =
|
|
1789
|
-
import_fs9.default.existsSync(distPath) || (logger_default.error("Dist folder not found. Build the project first"), process.exit());
|
|
1790
|
-
let files = await (0, import_tinyglobby3.glob)(["**/*"], {
|
|
1791
|
-
cwd: distPath,
|
|
1792
|
-
onlyFiles: !0,
|
|
1793
|
-
absolute: !0
|
|
1612
|
+
// src/utils/getFiles.ts
|
|
1613
|
+
var import_fs9 = __toESM(require("fs")), import_path10 = __toESM(require("path")), import_tinyglobby3 = require("tinyglobby");
|
|
1614
|
+
init_logger();
|
|
1615
|
+
var getFiles = async () => {
|
|
1616
|
+
let distPath = import_path10.default.resolve("./dist");
|
|
1617
|
+
import_fs9.default.existsSync(distPath) || (logger_default.error("Dist folder not found. Build the project first"), process.exit());
|
|
1618
|
+
let files = await (0, import_tinyglobby3.glob)(["**/*"], {
|
|
1619
|
+
cwd: distPath,
|
|
1620
|
+
onlyFiles: !0,
|
|
1621
|
+
absolute: !0
|
|
1622
|
+
});
|
|
1623
|
+
return logger_default.info(`\u{1F4C1} Found ${files.length} files to upload`), files;
|
|
1624
|
+
};
|
|
1625
|
+
|
|
1626
|
+
// src/commands/deploy/index.ts
|
|
1627
|
+
async function deploy() {
|
|
1628
|
+
await s3Manager.checkS3Auth();
|
|
1629
|
+
let environment = await promptEnvironment();
|
|
1630
|
+
s3Manager.setEnvironment(environment);
|
|
1631
|
+
let manifest = await manifestManager.load();
|
|
1632
|
+
await build({ environment });
|
|
1633
|
+
let files = await getFiles();
|
|
1634
|
+
await s3Manager.uploadPluginFiles(manifest, files);
|
|
1635
|
+
}
|
|
1636
|
+
|
|
1637
|
+
// src/api/tracker.ts
|
|
1638
|
+
var import_form_data = __toESM(require("form-data"));
|
|
1639
|
+
|
|
1640
|
+
// src/api/trackerApiRequest.ts
|
|
1641
|
+
var import_node_fetch2 = __toESM(require("node-fetch"));
|
|
1642
|
+
|
|
1643
|
+
// src/core/auth/authManager.ts
|
|
1644
|
+
var fs11 = __toESM(require("fs")), os3 = __toESM(require("os")), path15 = __toESM(require("path")), authDir = path15.join(os3.homedir(), ".tracker-cli"), authFile = path15.join(authDir, "auth.json"), getData = () => {
|
|
1645
|
+
try {
|
|
1646
|
+
if (!fs11.existsSync(authFile))
|
|
1647
|
+
return null;
|
|
1648
|
+
let data = fs11.readFileSync(authFile, "utf-8");
|
|
1649
|
+
return JSON.parse(data);
|
|
1650
|
+
} catch {
|
|
1651
|
+
return null;
|
|
1652
|
+
}
|
|
1653
|
+
}, getAuthHeader = () => {
|
|
1654
|
+
let authData = getData();
|
|
1655
|
+
return authData ? `OAuth ${authData.token}` : null;
|
|
1656
|
+
}, saveAuthData = (token) => {
|
|
1657
|
+
let authData = {
|
|
1658
|
+
token
|
|
1659
|
+
};
|
|
1660
|
+
fs11.existsSync(authDir) || fs11.mkdirSync(authDir, { recursive: !0, mode: 448 }), fs11.writeFileSync(authFile, JSON.stringify(authData, null, 2), {
|
|
1661
|
+
mode: 384
|
|
1662
|
+
});
|
|
1663
|
+
}, removeAuthData = () => {
|
|
1664
|
+
fs11.existsSync(authFile) && fs11.unlinkSync(authFile);
|
|
1665
|
+
}, authManager = {
|
|
1666
|
+
get authHeader() {
|
|
1667
|
+
return getAuthHeader();
|
|
1668
|
+
},
|
|
1669
|
+
get data() {
|
|
1670
|
+
return getData();
|
|
1671
|
+
},
|
|
1672
|
+
saveAuthData,
|
|
1673
|
+
removeAuthData
|
|
1674
|
+
};
|
|
1675
|
+
|
|
1676
|
+
// src/api/trackerApiRequest.ts
|
|
1677
|
+
function buildQueryString(queryParams) {
|
|
1678
|
+
if (!queryParams || Object.keys(queryParams).length === 0)
|
|
1679
|
+
return "";
|
|
1680
|
+
let params = new URLSearchParams();
|
|
1681
|
+
return Object.entries(queryParams).forEach(([key, value]) => {
|
|
1682
|
+
params.append(key, String(value));
|
|
1683
|
+
}), `?${params.toString()}`;
|
|
1684
|
+
}
|
|
1685
|
+
async function parseResponse(response) {
|
|
1686
|
+
return response.status === 204 || response.headers.get("content-length") === "0" ? void 0 : response.headers.get("content-type")?.includes("application/json") ? await response.json() : await response.text();
|
|
1687
|
+
}
|
|
1688
|
+
async function trackerApiRequest(endpoint, options = {}) {
|
|
1689
|
+
let { method = "GET", body, headers = {}, formData, queryParams } = options, authHeader = authManager.authHeader;
|
|
1690
|
+
if (!authHeader)
|
|
1691
|
+
throw new Error('Not authenticated. Run "tracker-cli login" first.');
|
|
1692
|
+
let requestHeaders = {
|
|
1693
|
+
Authorization: authHeader,
|
|
1694
|
+
Accept: "application/json",
|
|
1695
|
+
...headers
|
|
1696
|
+
}, requestBody;
|
|
1697
|
+
if (formData) {
|
|
1698
|
+
let formHeaders = formData.getHeaders?.();
|
|
1699
|
+
Object.assign(requestHeaders, formHeaders), requestBody = formData;
|
|
1700
|
+
} else body && method !== "GET" && (requestHeaders["Content-Type"] = "application/json", requestBody = JSON.stringify(body));
|
|
1701
|
+
let queryString = buildQueryString(queryParams), url = `${getTrackerBaseUrl2()}${endpoint}${queryString}`, response = await (0, import_node_fetch2.default)(url, {
|
|
1702
|
+
method,
|
|
1703
|
+
headers: requestHeaders,
|
|
1704
|
+
body: requestBody
|
|
1705
|
+
});
|
|
1706
|
+
if (!response.ok) {
|
|
1707
|
+
let errorText = await response.text(), errorMessage = `Tracker API error ${response.status}: ${errorText}`;
|
|
1708
|
+
try {
|
|
1709
|
+
let errorJson = JSON.parse(errorText);
|
|
1710
|
+
errorJson.message && (errorMessage = `Tracker API error ${response.status}: ${errorJson.message}`);
|
|
1711
|
+
} catch {
|
|
1712
|
+
}
|
|
1713
|
+
throw new Error(errorMessage);
|
|
1714
|
+
}
|
|
1715
|
+
return parseResponse(response);
|
|
1716
|
+
}
|
|
1717
|
+
|
|
1718
|
+
// src/api/tracker.ts
|
|
1719
|
+
var PLUGINMOD_QUEUE = "PLUGINMOD";
|
|
1720
|
+
function buildIssueSummary(slug) {
|
|
1721
|
+
return `Plugin: ${slug}`;
|
|
1722
|
+
}
|
|
1723
|
+
function buildIssueDescription(params) {
|
|
1724
|
+
let { pluginId, slug, version, manifestJson, catalogName, catalogDescription, catalogTags } = params, lines = [
|
|
1725
|
+
`**Plugin UUID:** ${pluginId}`,
|
|
1726
|
+
`**Slug:** ${slug}`,
|
|
1727
|
+
`**Version:** ${version}`
|
|
1728
|
+
];
|
|
1729
|
+
return catalogName && lines.push(`**Name:** ${catalogName}`), catalogDescription && lines.push(`**Description:** ${catalogDescription}`), catalogTags && catalogTags.length > 0 && lines.push(`**Tags:** ${catalogTags.join(", ")}`), lines.push("", "**Manifest:**", "```json", manifestJson, "```"), lines.join(`
|
|
1730
|
+
`);
|
|
1731
|
+
}
|
|
1732
|
+
async function createPluginIssue(params) {
|
|
1733
|
+
let { slug, pluginId, version, manifestJson } = params, body = {
|
|
1734
|
+
queue: PLUGINMOD_QUEUE,
|
|
1735
|
+
summary: buildIssueSummary(slug),
|
|
1736
|
+
description: buildIssueDescription({ pluginId, slug, version, manifestJson }),
|
|
1737
|
+
tags: ["tracker-plugin"]
|
|
1738
|
+
};
|
|
1739
|
+
return trackerApiRequest("/issues", {
|
|
1740
|
+
method: "POST",
|
|
1741
|
+
body
|
|
1742
|
+
});
|
|
1743
|
+
}
|
|
1744
|
+
async function updatePluginIssue(issueKey, params) {
|
|
1745
|
+
return trackerApiRequest(`/issues/${issueKey}`, {
|
|
1746
|
+
method: "PATCH",
|
|
1747
|
+
body: params
|
|
1748
|
+
});
|
|
1749
|
+
}
|
|
1750
|
+
async function attachFileToIssue(issueKey, fileBuffer, fileName) {
|
|
1751
|
+
let formData = new import_form_data.default();
|
|
1752
|
+
return formData.append("file", fileBuffer, {
|
|
1753
|
+
filename: fileName,
|
|
1754
|
+
contentType: "application/zip"
|
|
1755
|
+
}), trackerApiRequest(`/issues/${issueKey}/attachments`, {
|
|
1756
|
+
method: "POST",
|
|
1757
|
+
formData
|
|
1758
|
+
});
|
|
1759
|
+
}
|
|
1760
|
+
async function getIssueTransitions(issueKey) {
|
|
1761
|
+
return trackerApiRequest(`/issues/${issueKey}/transitions`, {
|
|
1762
|
+
method: "GET"
|
|
1763
|
+
});
|
|
1764
|
+
}
|
|
1765
|
+
async function executeIssueTransition(issueKey, transitionId) {
|
|
1766
|
+
await trackerApiRequest(`/issues/${issueKey}/transitions/${transitionId}/_execute`, {
|
|
1767
|
+
method: "POST",
|
|
1768
|
+
body: {}
|
|
1769
|
+
});
|
|
1770
|
+
}
|
|
1771
|
+
async function getIssue(issueKey) {
|
|
1772
|
+
return trackerApiRequest(`/issues/${issueKey}`, {
|
|
1773
|
+
method: "GET"
|
|
1774
|
+
});
|
|
1775
|
+
}
|
|
1776
|
+
async function getMyPluginIssues() {
|
|
1777
|
+
return trackerApiRequest("/issues/_search", {
|
|
1778
|
+
method: "POST",
|
|
1779
|
+
body: {
|
|
1780
|
+
filter: {
|
|
1781
|
+
queue: PLUGINMOD_QUEUE,
|
|
1782
|
+
createdBy: "me()"
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
});
|
|
1786
|
+
}
|
|
1787
|
+
async function addIssueComment(issueKey, text) {
|
|
1788
|
+
await trackerApiRequest(`/issues/${issueKey}/comments`, {
|
|
1789
|
+
method: "POST",
|
|
1790
|
+
body: { text }
|
|
1794
1791
|
});
|
|
1795
|
-
return logger_default.info(`\u{1F4C1} Found ${files.length} files to upload`), files;
|
|
1796
|
-
};
|
|
1797
|
-
|
|
1798
|
-
// src/commands/deploy/index.ts
|
|
1799
|
-
async function deploy() {
|
|
1800
|
-
let environment = await promptEnvironment2();
|
|
1801
|
-
await s3Manager.setEnvironment(environment), await s3Manager.checkS3Auth();
|
|
1802
|
-
let manifest = await manifestManager.load();
|
|
1803
|
-
await build({ environment });
|
|
1804
|
-
let files = await getFiles();
|
|
1805
|
-
await s3Manager.uploadPluginFiles(manifest, files);
|
|
1806
1792
|
}
|
|
1807
1793
|
|
|
1808
1794
|
// src/api/utils.ts
|
|
@@ -1837,6 +1823,32 @@ function mapTrackerStatusToPluginStatus(issue) {
|
|
|
1837
1823
|
}
|
|
1838
1824
|
}
|
|
1839
1825
|
|
|
1826
|
+
// src/core/pluginState/pluginStateManager.ts
|
|
1827
|
+
var import_fs10 = require("fs"), import_promises3 = require("fs/promises"), STATE_FILE = ".tracker-plugin", load2 = async () => {
|
|
1828
|
+
if (!(0, import_fs10.existsSync)(STATE_FILE))
|
|
1829
|
+
return {};
|
|
1830
|
+
try {
|
|
1831
|
+
let content = await (0, import_promises3.readFile)(STATE_FILE, "utf8");
|
|
1832
|
+
return JSON.parse(content);
|
|
1833
|
+
} catch {
|
|
1834
|
+
return {};
|
|
1835
|
+
}
|
|
1836
|
+
}, save2 = async (state) => {
|
|
1837
|
+
try {
|
|
1838
|
+
let content = JSON.stringify(state, null, 4);
|
|
1839
|
+
await (0, import_promises3.writeFile)(STATE_FILE, content, "utf8");
|
|
1840
|
+
} catch (error2) {
|
|
1841
|
+
throw error2 instanceof Error ? new Error(`Error saving ${STATE_FILE}: ${error2.message}`) : new Error(`Error saving ${STATE_FILE}`);
|
|
1842
|
+
}
|
|
1843
|
+
}, update2 = async (updates) => {
|
|
1844
|
+
let updated = { ...await load2(), ...updates };
|
|
1845
|
+
return await save2(updated), updated;
|
|
1846
|
+
}, pluginStateManager = {
|
|
1847
|
+
load: load2,
|
|
1848
|
+
save: save2,
|
|
1849
|
+
update: update2
|
|
1850
|
+
};
|
|
1851
|
+
|
|
1840
1852
|
// src/commands/info/index.ts
|
|
1841
1853
|
init_logger();
|
|
1842
1854
|
|
|
@@ -1860,9 +1872,8 @@ var printHeader = (title) => {
|
|
|
1860
1872
|
console.info(` ${import_picocolors3.default.dim(label.padEnd(minWidth))} ${value}`);
|
|
1861
1873
|
}, printPluginId = (pluginId) => {
|
|
1862
1874
|
printField("Plugin ID", import_picocolors3.default.cyan(pluginId));
|
|
1863
|
-
}
|
|
1864
|
-
|
|
1865
|
-
}, printStatus = (status) => {
|
|
1875
|
+
};
|
|
1876
|
+
var printStatus = (status) => {
|
|
1866
1877
|
printField("Status", getStatusBadge(status.toUpperCase()));
|
|
1867
1878
|
}, printCreated = (createdAt) => {
|
|
1868
1879
|
printField("Created", import_picocolors3.default.white(formatDate(createdAt)));
|
|
@@ -1881,23 +1892,9 @@ function showPluginVersions(versions2) {
|
|
|
1881
1892
|
console.info(` ${import_picocolors3.default.bold(String(index + 1) + ".")} ${import_picocolors3.default.cyan(version.versionId)}`), printField("Status", getStatusBadge(version.status.toUpperCase())), printField("Version", import_picocolors3.default.white(version.version)), printCreated(version.createdAt), logger_default.newLine();
|
|
1882
1893
|
});
|
|
1883
1894
|
}
|
|
1884
|
-
function showPluginList(plugins) {
|
|
1885
|
-
if (!plugins || plugins.length === 0) {
|
|
1886
|
-
console.info(import_picocolors3.default.dim(" No plugins found")), logger_default.newLine();
|
|
1887
|
-
return;
|
|
1888
|
-
}
|
|
1889
|
-
printHeader(`\u{1F4CB} Your Plugins \xB7 ${plugins.length}`), logger_default.newLine(), plugins.forEach((plugin) => {
|
|
1890
|
-
console.info(
|
|
1891
|
-
` ${import_picocolors3.default.magenta(plugin.slug)} ${import_picocolors3.default.dim("\xB7")} ${getStatusBadge(plugin.status.toUpperCase())} ${import_picocolors3.default.dim("\xB7")} ${import_picocolors3.default.cyan(plugin.id)}`
|
|
1892
|
-
), logger_default.newLine();
|
|
1893
|
-
});
|
|
1894
|
-
}
|
|
1895
1895
|
function showPluginCreated(data) {
|
|
1896
1896
|
printSuccessHeader("\u2705 Plugin Created"), logger_default.newLine(), printPluginId(data.id);
|
|
1897
1897
|
}
|
|
1898
|
-
function showPluginSubmitted(data) {
|
|
1899
|
-
printSuccessHeader("\u{1F680} Plugin Submitted"), logger_default.newLine(), printPluginId(data.pluginId), printVersionId(data.versionId), printStatus(data.status);
|
|
1900
|
-
}
|
|
1901
1898
|
function showTrackerPluginList(issues, mapStatus) {
|
|
1902
1899
|
if (!issues || issues.length === 0) {
|
|
1903
1900
|
console.info(import_picocolors3.default.dim(" No plugins found")), logger_default.newLine();
|
|
@@ -1959,12 +1956,13 @@ var mergeConfigs = (config, newConfig) => {
|
|
|
1959
1956
|
|
|
1960
1957
|
// src/commands/install/index.ts
|
|
1961
1958
|
async function install() {
|
|
1962
|
-
|
|
1963
|
-
|
|
1959
|
+
await s3Manager.checkMdsAuth();
|
|
1960
|
+
let environment = await promptEnvironment();
|
|
1961
|
+
s3Manager.setEnvironment(environment);
|
|
1964
1962
|
let [config, manifest] = await Promise.all([
|
|
1965
1963
|
s3Manager.getPluginsConfig(),
|
|
1966
1964
|
manifestManager.load()
|
|
1967
|
-
]),
|
|
1965
|
+
]), pluginConfig = convertManifestToConfig(manifest, environment), mergedConfig = mergeConfigs(config, pluginConfig);
|
|
1968
1966
|
await s3Manager.savePluginsConfig(mergedConfig), logger_default.info("\u{1F389} Installation completed successfully!");
|
|
1969
1967
|
}
|
|
1970
1968
|
|
|
@@ -2000,7 +1998,7 @@ async function apiRequest(endpoint, options = {}) {
|
|
|
2000
1998
|
headers: requestHeaders
|
|
2001
1999
|
};
|
|
2002
2000
|
body && method !== "GET" && (requestOptions.body = JSON.stringify(body));
|
|
2003
|
-
let url = `${
|
|
2001
|
+
let url = `${getTrackerBaseUrl2()}${endpoint}`, response = await fetch(url, requestOptions);
|
|
2004
2002
|
if (!response.ok)
|
|
2005
2003
|
throw new Error([response.status, response.statusText].join(" ").trim());
|
|
2006
2004
|
let contentType = response.headers.get("content-type");
|
|
@@ -2020,13 +2018,13 @@ init_logger();
|
|
|
2020
2018
|
|
|
2021
2019
|
// src/commands/login/utils/promptForCredentials.ts
|
|
2022
2020
|
var import_prompts5 = require("@inquirer/prompts"), import_picocolors4 = __toESM(require("picocolors"));
|
|
2023
|
-
var
|
|
2024
|
-
let tokenUrl =
|
|
2025
|
-
return
|
|
2026
|
-
import_picocolors4.default.dim("Get your OAuth token at: ") + import_picocolors4.default.cyan(`${
|
|
2027
|
-
), console.info("")
|
|
2021
|
+
var ESC = "\x1B", BEL = "\x07", promptForCredentials = async () => {
|
|
2022
|
+
let tokenUrl = getOAuthTokenUrl2();
|
|
2023
|
+
return console.info(
|
|
2024
|
+
import_picocolors4.default.dim("Get your OAuth token at: ") + import_picocolors4.default.cyan(`${ESC}]8;;${tokenUrl}${BEL}${tokenUrl}${ESC}]8;;${BEL}`)
|
|
2025
|
+
), console.info(""), {
|
|
2028
2026
|
token: (await (0, import_prompts5.input)({
|
|
2029
|
-
message: "Enter your OAuth token:",
|
|
2027
|
+
message: "Enter your Yandex Tracker OAuth token:",
|
|
2030
2028
|
required: !0
|
|
2031
2029
|
})).trim()
|
|
2032
2030
|
};
|
|
@@ -2058,66 +2056,10 @@ function logout() {
|
|
|
2058
2056
|
}
|
|
2059
2057
|
|
|
2060
2058
|
// src/commands/register/index.ts
|
|
2061
|
-
var import_crypto = require("crypto");
|
|
2062
2059
|
init_logger();
|
|
2063
|
-
async function register() {
|
|
2064
|
-
let manifest = await manifestManager.load(), state = await pluginStateManager.load();
|
|
2065
|
-
if (state.trackerIssueKey)
|
|
2066
|
-
try {
|
|
2067
|
-
let issue2 = await getIssue(state.trackerIssueKey);
|
|
2068
|
-
logger_default.error(
|
|
2069
|
-
`Plugin is already registered. Tracker issue: ${issue2.key} (${issue2.summary})`
|
|
2070
|
-
), process.exit(1);
|
|
2071
|
-
} catch {
|
|
2072
|
-
}
|
|
2073
|
-
let pluginId = manifest.id ?? (0, import_crypto.randomUUID)();
|
|
2074
|
-
logger_default.info("\u23F3 Creating plugin issue in Tracker..."), manifest.id || await manifestManager.update({ id: pluginId });
|
|
2075
|
-
let manifestJson = await manifestManager.loadRaw(), issue = await createPluginIssue({
|
|
2076
|
-
pluginId,
|
|
2077
|
-
slug: manifest.slug,
|
|
2078
|
-
version: manifest.version,
|
|
2079
|
-
manifestJson
|
|
2080
|
-
});
|
|
2081
|
-
await pluginStateManager.update({ trackerIssueKey: issue.key }), logger_default.success("Plugin registered!"), logger_default.info(` Tracker issue : ${issue.key}`), logger_default.info(` Summary : ${issue.summary}`), logger_default.info(` Plugin UUID : ${pluginId}`), logger_default.commands("\u{1F4A1} Next steps", [
|
|
2082
|
-
"tracker-cli catalog # Update catalog metadata",
|
|
2083
|
-
"tracker-cli upload # Build and upload plugin bundle",
|
|
2084
|
-
"tracker-cli submit # Submit for review"
|
|
2085
|
-
]);
|
|
2086
|
-
}
|
|
2087
2060
|
|
|
2088
2061
|
// src/commands/submit/index.ts
|
|
2089
2062
|
init_logger();
|
|
2090
|
-
var SUBMIT_TRANSITION_DISPLAY = "waiting for approve";
|
|
2091
|
-
async function submit() {
|
|
2092
|
-
let manifest = await manifestManager.load(), state = await pluginStateManager.load();
|
|
2093
|
-
if (!state.trackerIssueKey) {
|
|
2094
|
-
logger_default.warning('Plugin is not registered yet. Run "tracker-cli register" first.'), logger_default.suggest("tracker-cli register");
|
|
2095
|
-
return;
|
|
2096
|
-
}
|
|
2097
|
-
let issueKey = state.trackerIssueKey;
|
|
2098
|
-
logger_default.info(`\u23F3 Checking for uploaded bundle on ${issueKey}...`);
|
|
2099
|
-
let attachments = await getIssueAttachments(issueKey), archiveName = `${manifest.slug}-${manifest.version}.zip`;
|
|
2100
|
-
if (!attachments.some((a) => a.name === archiveName)) {
|
|
2101
|
-
logger_default.warning(
|
|
2102
|
-
`No bundle found for version ${manifest.version}. Upload it first with "tracker-cli upload".`
|
|
2103
|
-
), logger_default.suggest("tracker-cli upload");
|
|
2104
|
-
return;
|
|
2105
|
-
}
|
|
2106
|
-
logger_default.info(`\u23F3 Fetching available transitions for ${issueKey}...`);
|
|
2107
|
-
let transitions = await getIssueTransitions(issueKey), submitTransition = transitions.find(
|
|
2108
|
-
(t) => t.display?.toLowerCase().includes(SUBMIT_TRANSITION_DISPLAY) || t.id?.toLowerCase().includes("waitingforapprove") || t.id?.toLowerCase().includes("waiting")
|
|
2109
|
-
);
|
|
2110
|
-
if (!submitTransition) {
|
|
2111
|
-
let available = transitions.map((t) => `"${t.display ?? t.id}"`).join(", ");
|
|
2112
|
-
logger_default.error(
|
|
2113
|
-
`Could not find a "Waiting for approve" transition on ${issueKey}. Available: ${available}`
|
|
2114
|
-
);
|
|
2115
|
-
return;
|
|
2116
|
-
}
|
|
2117
|
-
logger_default.info(
|
|
2118
|
-
`\u{1F680} Submitting plugin for review (transition: "${submitTransition.display ?? submitTransition.id}")...`
|
|
2119
|
-
), await executeIssueTransition(issueKey, submitTransition.id), await addIssueComment(issueKey, `Submitted version \`${manifest.version}\` for review.`), logger_default.success("Plugin submitted for review!"), logger_default.info(` Tracker issue : ${issueKey}`), logger_default.info(` Version : ${manifest.version}`);
|
|
2120
|
-
}
|
|
2121
2063
|
|
|
2122
2064
|
// src/commands/uninstall/index.ts
|
|
2123
2065
|
init_logger();
|
|
@@ -2136,8 +2078,7 @@ var removePluginFromConfig = (config, pluginSlug) => {
|
|
|
2136
2078
|
|
|
2137
2079
|
// src/commands/uninstall/index.ts
|
|
2138
2080
|
async function uninstall() {
|
|
2139
|
-
|
|
2140
|
-
await s3Manager.setEnvironment(environment), await s3Manager.checkMdsAuth();
|
|
2081
|
+
await s3Manager.checkMdsAuth();
|
|
2141
2082
|
let [config, manifest] = await Promise.all([
|
|
2142
2083
|
s3Manager.getPluginsConfig(),
|
|
2143
2084
|
manifestManager.load()
|
|
@@ -2159,26 +2100,32 @@ async function uninstall() {
|
|
|
2159
2100
|
}
|
|
2160
2101
|
|
|
2161
2102
|
// src/commands/up/utils/copyTemplateFiles.ts
|
|
2162
|
-
var
|
|
2103
|
+
var import_fs11 = require("fs"), import_promises4 = require("fs/promises");
|
|
2163
2104
|
var copyTemplateFiles = async (filenames) => {
|
|
2164
2105
|
await Promise.all(
|
|
2165
2106
|
filenames.map(async (filename) => {
|
|
2166
2107
|
let templatePath = getTemplatePath(filename), targetPath = `./${filename}`;
|
|
2167
|
-
(0,
|
|
2108
|
+
(0, import_fs11.existsSync)(templatePath) && (0, import_fs11.existsSync)(targetPath) && await (0, import_promises4.copyFile)(templatePath, targetPath);
|
|
2168
2109
|
})
|
|
2169
2110
|
);
|
|
2170
2111
|
};
|
|
2171
2112
|
|
|
2113
|
+
// src/commands/up/utils/updateManifestCompatibility.ts
|
|
2114
|
+
async function updateManifestCompatibility() {
|
|
2115
|
+
let manifest = await manifestManager.load(), updates = {};
|
|
2116
|
+
"manifest_version" in manifest || (updates.manifest_version = 1), "supported_services" in manifest || (updates.supported_services = ["tracker"]), Object.keys(updates).length > 0 && await manifestManager.update(updates);
|
|
2117
|
+
}
|
|
2118
|
+
|
|
2172
2119
|
// src/commands/up/utils/updatePackageDependencies.ts
|
|
2173
|
-
var
|
|
2120
|
+
var import_fs12 = require("fs"), import_promises5 = require("fs/promises");
|
|
2174
2121
|
var updatePackageDependencies = async (dependencies) => {
|
|
2175
2122
|
let packageJsonPath = "./package.json", templatePackageJsonPath = getTemplatePath("package.json");
|
|
2176
|
-
if (!(0,
|
|
2123
|
+
if (!(0, import_fs12.existsSync)(packageJsonPath) || !(0, import_fs12.existsSync)(templatePackageJsonPath))
|
|
2177
2124
|
return;
|
|
2178
|
-
let packageJsonContent = await (0,
|
|
2125
|
+
let packageJsonContent = await (0, import_promises5.readFile)(packageJsonPath, "utf-8"), templatePackageJsonContent = await (0, import_promises5.readFile)(templatePackageJsonPath, "utf-8"), packageJson = JSON.parse(packageJsonContent), templatePackageJson = JSON.parse(templatePackageJsonContent), updated = !1;
|
|
2179
2126
|
dependencies.forEach((dep) => {
|
|
2180
2127
|
packageJson.dependencies?.[dep] && templatePackageJson.dependencies?.[dep] && packageJson.dependencies[dep] !== templatePackageJson.dependencies[dep] && (packageJson.dependencies[dep] = templatePackageJson.dependencies[dep], updated = !0);
|
|
2181
|
-
}), updated && await (0,
|
|
2128
|
+
}), updated && await (0, import_promises5.writeFile)(packageJsonPath, JSON.stringify(packageJson, null, 4) + `
|
|
2182
2129
|
`, "utf-8");
|
|
2183
2130
|
};
|
|
2184
2131
|
|
|
@@ -2188,40 +2135,72 @@ var templateFiles = ["manifest.schema.json", "vite.config.ts"], templateDeps = [
|
|
|
2188
2135
|
"@yandex-data-ui/tracker-pub-api-types"
|
|
2189
2136
|
];
|
|
2190
2137
|
async function up() {
|
|
2191
|
-
await copyTemplateFiles(templateFiles), await updatePackageDependencies(templateDeps);
|
|
2138
|
+
await copyTemplateFiles(templateFiles), await updateManifestCompatibility(), await updatePackageDependencies(templateDeps);
|
|
2192
2139
|
}
|
|
2193
2140
|
|
|
2194
2141
|
// src/utils/buildArchive.ts
|
|
2195
|
-
var
|
|
2142
|
+
var import_path12 = __toESM(require("path")), import_archiver = __toESM(require("archiver"));
|
|
2196
2143
|
init_logger();
|
|
2197
2144
|
|
|
2198
2145
|
// src/utils/marketplace.ts
|
|
2199
|
-
var
|
|
2146
|
+
var import_fs13 = __toESM(require("fs")), import_path11 = __toESM(require("path"));
|
|
2200
2147
|
init_logger();
|
|
2201
2148
|
var MARKETPLACE_DIR = "marketplace", MARKETPLACE_INDEX_FILE = "index.md", MARKETPLACE_HEADER_IMAGE_FILE = "header-image.jpg", PUBLIC_DIR = "public", PUBLIC_LOGO_FILE = "logo.svg", MANIFEST_FILE = "manifest.json", DIST_DIR = "dist", SRC_DIR = "src", ensurePathExists = (targetPath, errorMessage) => {
|
|
2202
|
-
|
|
2149
|
+
import_fs13.default.existsSync(targetPath) || (logger_default.error(errorMessage), process.exit(1));
|
|
2150
|
+
}, ensureManifestCatalogFields = (manifest) => {
|
|
2151
|
+
(!manifest.name?.ru || !manifest.name?.en) && (logger_default.error(
|
|
2152
|
+
'Manifest field "name" is required for publishing. Add localized "name.ru" and "name.en" to ./manifest.json.'
|
|
2153
|
+
), process.exit(1)), (!manifest.description?.ru || !manifest.description?.en) && (logger_default.error(
|
|
2154
|
+
'Manifest field "description" is required for publishing. Add localized "description.ru" and "description.en" to ./manifest.json.'
|
|
2155
|
+
), process.exit(1));
|
|
2203
2156
|
};
|
|
2204
2157
|
function validateMarketplaceAssets() {
|
|
2205
|
-
let marketplaceDir =
|
|
2158
|
+
let marketplaceDir = import_path11.default.resolve(MARKETPLACE_DIR);
|
|
2206
2159
|
ensurePathExists(
|
|
2207
2160
|
marketplaceDir,
|
|
2208
2161
|
"Marketplace folder not found. Create ./marketplace and add index.md and header-image.jpg before publishing."
|
|
2209
2162
|
), ensurePathExists(
|
|
2210
|
-
|
|
2163
|
+
import_path11.default.join(marketplaceDir, MARKETPLACE_INDEX_FILE),
|
|
2211
2164
|
"Marketplace description not found. Add ./marketplace/index.md before publishing."
|
|
2212
2165
|
), ensurePathExists(
|
|
2213
|
-
|
|
2166
|
+
import_path11.default.join(marketplaceDir, MARKETPLACE_HEADER_IMAGE_FILE),
|
|
2214
2167
|
"Marketplace header image not found. Add ./marketplace/header-image.jpg before publishing."
|
|
2215
2168
|
), ensurePathExists(
|
|
2216
|
-
|
|
2169
|
+
import_path11.default.resolve(PUBLIC_DIR, PUBLIC_LOGO_FILE),
|
|
2217
2170
|
"Plugin logo not found. Add ./public/logo.svg before publishing."
|
|
2218
2171
|
);
|
|
2219
2172
|
}
|
|
2220
2173
|
function validateArchiveSources() {
|
|
2221
|
-
ensurePathExists(
|
|
2222
|
-
|
|
2174
|
+
ensurePathExists(import_path11.default.resolve(DIST_DIR), "Dist folder not found. Build the project first."), ensurePathExists(
|
|
2175
|
+
import_path11.default.resolve(SRC_DIR),
|
|
2223
2176
|
"Source folder not found. Add ./src before publishing."
|
|
2224
|
-
), ensurePathExists(
|
|
2177
|
+
), ensurePathExists(import_path11.default.resolve(MANIFEST_FILE), "manifest.json not found in plugin root."), validateMarketplaceAssets();
|
|
2178
|
+
}
|
|
2179
|
+
async function getMarketplaceCatalogEntry() {
|
|
2180
|
+
let indexPath = import_path11.default.resolve(MARKETPLACE_DIR, MARKETPLACE_INDEX_FILE);
|
|
2181
|
+
ensurePathExists(
|
|
2182
|
+
indexPath,
|
|
2183
|
+
"Marketplace description not found. Add ./marketplace/index.md before uploading."
|
|
2184
|
+
);
|
|
2185
|
+
let manifest = await manifestManager.load();
|
|
2186
|
+
ensureManifestCatalogFields(manifest);
|
|
2187
|
+
let longDescription = import_fs13.default.readFileSync(indexPath, "utf-8").trim();
|
|
2188
|
+
return {
|
|
2189
|
+
name: manifest.name.ru,
|
|
2190
|
+
description: manifest.description.ru,
|
|
2191
|
+
longDescription,
|
|
2192
|
+
tags: manifest.keywords ?? []
|
|
2193
|
+
};
|
|
2194
|
+
}
|
|
2195
|
+
function getMarketplaceHeaderImage() {
|
|
2196
|
+
let imagePath = import_path11.default.resolve(MARKETPLACE_DIR, MARKETPLACE_HEADER_IMAGE_FILE);
|
|
2197
|
+
return ensurePathExists(
|
|
2198
|
+
imagePath,
|
|
2199
|
+
"Marketplace header image not found. Add ./marketplace/header-image.jpg before uploading."
|
|
2200
|
+
), {
|
|
2201
|
+
buffer: import_fs13.default.readFileSync(imagePath),
|
|
2202
|
+
filename: MARKETPLACE_HEADER_IMAGE_FILE
|
|
2203
|
+
};
|
|
2225
2204
|
}
|
|
2226
2205
|
var marketplacePaths = {
|
|
2227
2206
|
distDir: DIST_DIR,
|
|
@@ -2231,41 +2210,55 @@ var marketplacePaths = {
|
|
|
2231
2210
|
};
|
|
2232
2211
|
|
|
2233
2212
|
// src/utils/buildArchive.ts
|
|
2213
|
+
init_verbose();
|
|
2234
2214
|
async function buildArchive() {
|
|
2235
|
-
return validateArchiveSources(),
|
|
2215
|
+
return validateArchiveSources(), (await manifestManager.load()).manifest_version === void 0 && (logger_default.error(
|
|
2216
|
+
'manifest_version is missing in manifest.json. Run "tracker-cli up" or add "manifest_version": 1 manually before uploading.'
|
|
2217
|
+
), process.exit(1)), new Promise((resolve2, reject) => {
|
|
2236
2218
|
let archive = (0, import_archiver.default)("zip", { zlib: { level: 9 } }), chunks = [];
|
|
2237
2219
|
archive.on("data", (chunk) => chunks.push(chunk)), archive.on("end", () => {
|
|
2238
2220
|
let buffer = Buffer.concat(chunks);
|
|
2239
|
-
logger_default.info(`\u{1F4E6} Archive created (${buffer.length} bytes)`),
|
|
2240
|
-
|
|
2221
|
+
if (logger_default.info(`\u{1F4E6} Archive created (${buffer.length} bytes)`), isVerboseEnabled()) {
|
|
2222
|
+
let debugPath = writeVerboseArtifact("archive/latest-upload.zip", buffer);
|
|
2223
|
+
logger_default.info(`[platform-api-debug] Saved archive copy to ${debugPath}`);
|
|
2224
|
+
}
|
|
2225
|
+
resolve2(buffer);
|
|
2226
|
+
}), archive.on("error", reject), archive.file(import_path12.default.resolve(marketplacePaths.manifestFile), { name: "manifest.json" }), archive.glob(
|
|
2227
|
+
"**/*",
|
|
2228
|
+
{
|
|
2229
|
+
cwd: import_path12.default.resolve(marketplacePaths.distDir),
|
|
2230
|
+
ignore: ["**/.DS_Store"]
|
|
2231
|
+
},
|
|
2232
|
+
{ prefix: "dist/" }
|
|
2233
|
+
), archive.glob(
|
|
2234
|
+
"**/*",
|
|
2235
|
+
{
|
|
2236
|
+
cwd: import_path12.default.resolve(marketplacePaths.srcDir),
|
|
2237
|
+
ignore: ["**/.DS_Store"]
|
|
2238
|
+
},
|
|
2239
|
+
{ prefix: "src/" }
|
|
2240
|
+
), archive.finalize();
|
|
2241
2241
|
});
|
|
2242
2242
|
}
|
|
2243
2243
|
|
|
2244
2244
|
// src/commands/upload/index.ts
|
|
2245
2245
|
init_logger();
|
|
2246
|
-
async function upload() {
|
|
2247
|
-
let manifest = await manifestManager.load(), state = await pluginStateManager.load();
|
|
2248
|
-
if (!state.trackerIssueKey) {
|
|
2249
|
-
logger_default.warning('Plugin is not registered yet. Run "tracker-cli register" first.'), logger_default.suggest("tracker-cli register");
|
|
2250
|
-
return;
|
|
2251
|
-
}
|
|
2252
|
-
logger_default.info("\u{1F528} Building plugin..."), await build(), logger_default.info("\u{1F4E6} Creating archive...");
|
|
2253
|
-
let archiveBuffer = await buildArchive(), archiveName = `${manifest.slug}-${manifest.version}.zip`;
|
|
2254
|
-
logger_default.info(`\u2B06\uFE0F Attaching ${archiveName} to ${state.trackerIssueKey}...`), await attachFileToIssue(state.trackerIssueKey, archiveBuffer, archiveName), await addIssueComment(
|
|
2255
|
-
state.trackerIssueKey,
|
|
2256
|
-
`Updated bundle: \`${archiveName}\` (${archiveBuffer.length} bytes)`
|
|
2257
|
-
), logger_default.success(`Bundle updated on ${state.trackerIssueKey}: ${archiveName}`);
|
|
2258
|
-
}
|
|
2259
2246
|
|
|
2260
2247
|
// src/api/platform.ts
|
|
2261
2248
|
var import_form_data2 = __toESM(require("form-data"));
|
|
2262
2249
|
|
|
2263
2250
|
// src/api/platformApiRequest.ts
|
|
2264
2251
|
var import_node_fetch3 = __toESM(require("node-fetch"));
|
|
2252
|
+
init_logger();
|
|
2253
|
+
init_verbose();
|
|
2254
|
+
var PLATFORM_API_TIMEOUT_MS = Number(process.env.TRACKER_CLI_PLATFORM_TIMEOUT_MS || 3e4);
|
|
2265
2255
|
function buildRequestHeaders(headers, formData) {
|
|
2266
|
-
let authHeader = authManager.authHeader
|
|
2256
|
+
let authHeader = authManager.authHeader;
|
|
2257
|
+
if (!authHeader)
|
|
2258
|
+
throw new Error('Not authenticated. Run "tracker-cli login" first.');
|
|
2259
|
+
let requestHeaders = {
|
|
2267
2260
|
Accept: "*/*",
|
|
2268
|
-
|
|
2261
|
+
Authorization: authHeader,
|
|
2269
2262
|
...headers
|
|
2270
2263
|
};
|
|
2271
2264
|
return formData || (requestHeaders["Content-Type"] = "application/json"), requestHeaders;
|
|
@@ -2300,25 +2293,52 @@ async function platformApiRequest(endpoint, options = {}) {
|
|
|
2300
2293
|
method,
|
|
2301
2294
|
headers: { ...requestHeaders, ...additionalHeaders },
|
|
2302
2295
|
body: requestBody
|
|
2303
|
-
}, queryString = buildQueryString2(queryParams), url = `${
|
|
2304
|
-
if (
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2296
|
+
}, queryString = buildQueryString2(queryParams), url = `${getPlatformBaseUrl2()}${endpoint}${queryString}`, controller = new AbortController(), timeout = setTimeout(() => controller.abort(), PLATFORM_API_TIMEOUT_MS);
|
|
2297
|
+
if (isVerboseEnabled() && (logger_default.info(
|
|
2298
|
+
`[platform-api-debug] Request: method=${method} url=${url} hasBody=${!!body} hasFormData=${!!formData} timeoutMs=${PLATFORM_API_TIMEOUT_MS}`
|
|
2299
|
+
), body !== void 0 && logger_default.info(`[platform-api-debug] Request body: ${JSON.stringify(body)}`), formData)) {
|
|
2300
|
+
let debugPath = writeVerboseArtifact(
|
|
2301
|
+
"requests/latest-form-data.txt",
|
|
2302
|
+
`method=${method}
|
|
2303
|
+
url=${url}
|
|
2304
|
+
headers=${JSON.stringify({ ...requestHeaders, ...additionalHeaders }, null, 2)}
|
|
2305
|
+
formData=present
|
|
2306
|
+
`
|
|
2307
|
+
);
|
|
2308
|
+
logger_default.info(`[platform-api-debug] Saved form-data request metadata to ${debugPath}`);
|
|
2309
|
+
}
|
|
2310
|
+
try {
|
|
2311
|
+
let response = await (0, import_node_fetch3.default)(url, {
|
|
2312
|
+
...requestOptions,
|
|
2313
|
+
signal: controller.signal
|
|
2314
|
+
});
|
|
2315
|
+
if (isVerboseEnabled() && logger_default.info(
|
|
2316
|
+
`[platform-api-debug] Response: method=${method} url=${url} status=${response.status} contentType=${response.headers.get("content-type") ?? "n/a"}`
|
|
2317
|
+
), !response.ok) {
|
|
2318
|
+
let errorText = await response.text(), errorMessage = errorText;
|
|
2319
|
+
try {
|
|
2320
|
+
let errorJson = JSON.parse(errorText);
|
|
2321
|
+
errorJson.message && (errorMessage = errorJson.message);
|
|
2322
|
+
} catch {
|
|
2323
|
+
}
|
|
2324
|
+
throw new Error(errorMessage);
|
|
2310
2325
|
}
|
|
2311
|
-
|
|
2326
|
+
return parseResponse2(response);
|
|
2327
|
+
} catch (error2) {
|
|
2328
|
+
throw error2 instanceof Error && error2.name === "AbortError" ? new Error(
|
|
2329
|
+
`Platform API request timed out after ${PLATFORM_API_TIMEOUT_MS}ms: ${method} ${url}`
|
|
2330
|
+
) : error2;
|
|
2331
|
+
} finally {
|
|
2332
|
+
clearTimeout(timeout);
|
|
2312
2333
|
}
|
|
2313
|
-
return parseResponse2(response);
|
|
2314
2334
|
}
|
|
2315
2335
|
|
|
2316
2336
|
// src/api/platform.ts
|
|
2317
|
-
async function createPlugin(
|
|
2337
|
+
async function createPlugin(archiveBuffer, archiveName) {
|
|
2318
2338
|
let formData = new import_form_data2.default();
|
|
2319
|
-
return formData.append("archive",
|
|
2320
|
-
filename:
|
|
2321
|
-
contentType: "application/
|
|
2339
|
+
return formData.append("archive", archiveBuffer, {
|
|
2340
|
+
filename: archiveName,
|
|
2341
|
+
contentType: "application/zip"
|
|
2322
2342
|
}), platformApiRequest("/api/v1/plugins", {
|
|
2323
2343
|
method: "POST",
|
|
2324
2344
|
formData
|
|
@@ -2340,6 +2360,16 @@ async function updateCatalogEntry(pluginId, catalogData) {
|
|
|
2340
2360
|
body: catalogData
|
|
2341
2361
|
});
|
|
2342
2362
|
}
|
|
2363
|
+
async function updateCatalogImage(pluginId, imageBuffer, imageName) {
|
|
2364
|
+
let formData = new import_form_data2.default();
|
|
2365
|
+
return formData.append("image", imageBuffer, {
|
|
2366
|
+
filename: imageName,
|
|
2367
|
+
contentType: "image/jpeg"
|
|
2368
|
+
}), platformApiRequest(`/api/v1/plugins/${pluginId}/catalog-image`, {
|
|
2369
|
+
method: "PUT",
|
|
2370
|
+
formData
|
|
2371
|
+
});
|
|
2372
|
+
}
|
|
2343
2373
|
async function submitPlugin(pluginId, version) {
|
|
2344
2374
|
return platformApiRequest(`/api/v1/plugins/${pluginId}/submit`, {
|
|
2345
2375
|
method: "POST",
|
|
@@ -2358,11 +2388,6 @@ async function getPluginVersions(pluginId) {
|
|
|
2358
2388
|
method: "GET"
|
|
2359
2389
|
});
|
|
2360
2390
|
}
|
|
2361
|
-
async function getMyPlugins() {
|
|
2362
|
-
return platformApiRequest("/api/v1/plugins/my", {
|
|
2363
|
-
method: "GET"
|
|
2364
|
-
});
|
|
2365
|
-
}
|
|
2366
2391
|
async function checkSlugAvailability(slug) {
|
|
2367
2392
|
return platformApiRequest(`/api/v1/slugs/${slug}/available`, {
|
|
2368
2393
|
method: "GET"
|
|
@@ -2415,19 +2440,6 @@ async function whoami() {
|
|
|
2415
2440
|
}
|
|
2416
2441
|
}
|
|
2417
2442
|
|
|
2418
|
-
// src/commands/catalog/platform.ts
|
|
2419
|
-
init_logger();
|
|
2420
|
-
async function catalogPlatform() {
|
|
2421
|
-
let manifest = await manifestManager.load(), pluginId = await promptPluginId(manifest);
|
|
2422
|
-
logger_default.newLine(), logger_default.info("\u{1F4DD} Catalog entry information:");
|
|
2423
|
-
let name = await promptPluginName(), description = await promptPluginDescription(), tags = await promptPluginTags();
|
|
2424
|
-
logger_default.newLine(), logger_default.info("\u{1F4E4} Updating catalog entry..."), await updateCatalogEntry(pluginId, {
|
|
2425
|
-
name,
|
|
2426
|
-
description,
|
|
2427
|
-
tags
|
|
2428
|
-
}), logger_default.success("Catalog entry updated successfully!");
|
|
2429
|
-
}
|
|
2430
|
-
|
|
2431
2443
|
// src/commands/info/platform.ts
|
|
2432
2444
|
init_logger();
|
|
2433
2445
|
async function infoPlatform(pluginId) {
|
|
@@ -2441,36 +2453,6 @@ async function infoPlatform(pluginId) {
|
|
|
2441
2453
|
}
|
|
2442
2454
|
}
|
|
2443
2455
|
|
|
2444
|
-
// src/commands/list/platform.ts
|
|
2445
|
-
init_logger();
|
|
2446
|
-
async function listPlatform() {
|
|
2447
|
-
logger_default.info("\u23F3 Fetching my plugins...");
|
|
2448
|
-
try {
|
|
2449
|
-
let plugins = await getMyPlugins();
|
|
2450
|
-
showPluginList(plugins);
|
|
2451
|
-
} catch (error2) {
|
|
2452
|
-
throw logger_default.error("Failed to fetch plugins list"), error2;
|
|
2453
|
-
}
|
|
2454
|
-
}
|
|
2455
|
-
|
|
2456
|
-
// src/commands/register/platform.ts
|
|
2457
|
-
init_logger();
|
|
2458
|
-
async function registerPlatform() {
|
|
2459
|
-
let manifest = await manifestManager.load();
|
|
2460
|
-
if (manifest.id)
|
|
2461
|
-
try {
|
|
2462
|
-
let pluginInfo = await getPluginInfo(manifest.id);
|
|
2463
|
-
logger_default.error(`Plugin is already registered with ID: ${pluginInfo.id}`), process.exit(1);
|
|
2464
|
-
} catch {
|
|
2465
|
-
}
|
|
2466
|
-
await build(), logger_default.info("\u23F3 Creating plugin...");
|
|
2467
|
-
let manifestContent = await manifestManager.loadRaw(), response = await createPlugin(manifestContent);
|
|
2468
|
-
showPluginCreated(response), await manifestManager.update({ id: response.id }), logger_default.commands("\u{1F4A1} Next steps", [
|
|
2469
|
-
"tracker-cli catalog # Update catalog data",
|
|
2470
|
-
"tracker-cli submit # Submit for review"
|
|
2471
|
-
]);
|
|
2472
|
-
}
|
|
2473
|
-
|
|
2474
2456
|
// src/commands/submit/platform.ts
|
|
2475
2457
|
init_logger();
|
|
2476
2458
|
|
|
@@ -2502,44 +2484,115 @@ async function validateAndGetUniqueSlug(currentSlug) {
|
|
|
2502
2484
|
}
|
|
2503
2485
|
|
|
2504
2486
|
// src/commands/submit/platform.ts
|
|
2487
|
+
var SUBMIT_TRANSITION_DISPLAY = "waiting for approve";
|
|
2505
2488
|
async function submitPlatform() {
|
|
2506
|
-
let manifest = await manifestManager.load(),
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2489
|
+
let manifest = await manifestManager.load(), state = await pluginStateManager.load();
|
|
2490
|
+
validateMarketplaceAssets(), await build(), logger_default.info("\u{1F4E6} Creating archive...");
|
|
2491
|
+
let archiveBuffer = await buildArchive(), archiveName = `${manifest.slug}-${manifest.version}.zip`, pluginId = manifest.id;
|
|
2492
|
+
if (pluginId)
|
|
2493
|
+
logger_default.info("\u{1F4E4} Updating plugin archive..."), await updatePluginArchive(pluginId, archiveBuffer, archiveName);
|
|
2494
|
+
else {
|
|
2495
|
+
logger_default.info("\u23F3 Creating plugin...");
|
|
2496
|
+
let createdPlugin = await createPlugin(archiveBuffer, archiveName);
|
|
2497
|
+
showPluginCreated(createdPlugin), pluginId = createdPlugin.id, await manifestManager.update({ id: pluginId });
|
|
2498
|
+
}
|
|
2499
|
+
let manifestContent = await manifestManager.loadRaw(), issueKey = state.trackerIssueKey;
|
|
2500
|
+
if (!issueKey) {
|
|
2501
|
+
logger_default.info("\u23F3 Creating plugin issue in Tracker...");
|
|
2502
|
+
let issue = await createPluginIssue({
|
|
2503
|
+
pluginId,
|
|
2504
|
+
slug: manifest.slug,
|
|
2505
|
+
version: manifest.version,
|
|
2506
|
+
manifestJson: manifestContent
|
|
2507
|
+
});
|
|
2508
|
+
await pluginStateManager.update({ trackerIssueKey: issue.key }), issueKey = issue.key;
|
|
2510
2509
|
}
|
|
2510
|
+
let catalogEntry = await getMarketplaceCatalogEntry();
|
|
2511
|
+
logger_default.info("\u{1F4DD} Updating catalog entry from ./marketplace/index.md..."), await updateCatalogEntry(pluginId, catalogEntry);
|
|
2512
|
+
let headerImage = getMarketplaceHeaderImage();
|
|
2513
|
+
logger_default.info("\u{1F5BC}\uFE0F Uploading catalog image from ./marketplace/header-image.jpg..."), await updateCatalogImage(pluginId, headerImage.buffer, headerImage.filename);
|
|
2511
2514
|
let validatedSlug = await validateAndGetUniqueSlug(manifest.slug);
|
|
2512
|
-
validatedSlug !== manifest.slug && await manifestManager.update({ slug: validatedSlug });
|
|
2513
|
-
let
|
|
2514
|
-
|
|
2515
|
+
validatedSlug !== manifest.slug && await manifestManager.update({ slug: validatedSlug }), await submitPlugin(pluginId, manifest.version);
|
|
2516
|
+
let transitions = await getIssueTransitions(issueKey), submitTransition = transitions.find(
|
|
2517
|
+
(t) => t.display?.toLowerCase().includes(SUBMIT_TRANSITION_DISPLAY) || t.id?.toLowerCase().includes("waitingforapprove") || t.id?.toLowerCase().includes("waiting")
|
|
2518
|
+
);
|
|
2519
|
+
if (!submitTransition) {
|
|
2520
|
+
let available = transitions.map((t) => `"${t.display ?? t.id}"`).join(", ");
|
|
2521
|
+
logger_default.error(
|
|
2522
|
+
`Could not find a "Waiting for approve" transition on ${issueKey}. Available: ${available}`
|
|
2523
|
+
);
|
|
2524
|
+
return;
|
|
2525
|
+
}
|
|
2526
|
+
logger_default.info("\u{1F680} Submitting for review..."), await executeIssueTransition(issueKey, submitTransition.id), await addIssueComment(issueKey, `Submitted version \`${manifest.version}\` for review.`), logger_default.success("Plugin submitted for review!"), logger_default.info(` Tracker issue : ${issueKey}`), logger_default.info(` Version : ${manifest.version}`), logger_default.newLine();
|
|
2515
2527
|
}
|
|
2516
2528
|
|
|
2517
|
-
// src/commands/
|
|
2529
|
+
// src/commands/submit/tracker.ts
|
|
2530
|
+
var import_crypto = require("crypto");
|
|
2518
2531
|
init_logger();
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2532
|
+
var SUBMIT_TRANSITION_DISPLAY2 = "waiting for approve";
|
|
2533
|
+
async function submitTracker() {
|
|
2534
|
+
let manifest = await manifestManager.load(), issueKey = (await pluginStateManager.load()).trackerIssueKey;
|
|
2535
|
+
if (issueKey)
|
|
2536
|
+
try {
|
|
2537
|
+
await getIssue(issueKey);
|
|
2538
|
+
} catch {
|
|
2539
|
+
issueKey = void 0;
|
|
2540
|
+
}
|
|
2541
|
+
let pluginId = manifest.id ?? (0, import_crypto.randomUUID)();
|
|
2542
|
+
manifest.id || await manifestManager.update({ id: pluginId });
|
|
2543
|
+
let manifestJson = await manifestManager.loadRaw();
|
|
2544
|
+
if (issueKey) {
|
|
2545
|
+
logger_default.verbose(`\u23F3 Updating issue ${issueKey} with latest manifest...`);
|
|
2546
|
+
let issueDescription = buildIssueDescription({
|
|
2547
|
+
pluginId,
|
|
2548
|
+
slug: manifest.slug,
|
|
2549
|
+
version: manifest.version,
|
|
2550
|
+
manifestJson
|
|
2551
|
+
});
|
|
2552
|
+
await updatePluginIssue(issueKey, { description: issueDescription });
|
|
2553
|
+
} else {
|
|
2554
|
+
logger_default.info("\u23F3 Creating plugin issue in Tracker...");
|
|
2555
|
+
let issue = await createPluginIssue({
|
|
2556
|
+
pluginId,
|
|
2557
|
+
slug: manifest.slug,
|
|
2558
|
+
version: manifest.version,
|
|
2559
|
+
manifestJson
|
|
2560
|
+
});
|
|
2561
|
+
await pluginStateManager.update({ trackerIssueKey: issue.key }), issueKey = issue.key, logger_default.info(` Tracker issue : ${issueKey}`);
|
|
2524
2562
|
}
|
|
2525
|
-
await build(), logger_default.info("\u{1F4E6} Creating archive...");
|
|
2563
|
+
logger_default.info("\u{1F528} Building plugin..."), await build(), logger_default.info("\u{1F4E6} Creating archive...");
|
|
2526
2564
|
let archiveBuffer = await buildArchive(), archiveName = `${manifest.slug}-${manifest.version}.zip`;
|
|
2527
|
-
logger_default.
|
|
2565
|
+
logger_default.verbose(`\u2B06\uFE0F Attaching ${archiveName} to ${issueKey}...`), await attachFileToIssue(issueKey, archiveBuffer, archiveName), await addIssueComment(
|
|
2566
|
+
issueKey,
|
|
2567
|
+
`Updated bundle: \`${archiveName}\` (${archiveBuffer.length} bytes)`
|
|
2568
|
+
), logger_default.verbose(`\u23F3 Fetching available transitions for ${issueKey}...`);
|
|
2569
|
+
let transitions = await getIssueTransitions(issueKey), submitTransition = transitions.find(
|
|
2570
|
+
(t) => t.display?.toLowerCase().includes(SUBMIT_TRANSITION_DISPLAY2) || t.id?.toLowerCase().includes("waitingforapprove") || t.id?.toLowerCase().includes("waiting")
|
|
2571
|
+
);
|
|
2572
|
+
if (!submitTransition) {
|
|
2573
|
+
let available = transitions.map((t) => `"${t.display ?? t.id}"`).join(", ");
|
|
2574
|
+
logger_default.error(
|
|
2575
|
+
`Could not find a "Waiting for approve" transition on ${issueKey}. Available: ${available}`
|
|
2576
|
+
);
|
|
2577
|
+
return;
|
|
2578
|
+
}
|
|
2579
|
+
logger_default.info("\u{1F680} Submitting plugin for review..."), await executeIssueTransition(issueKey, submitTransition.id), await addIssueComment(issueKey, `Submitted version \`${manifest.version}\` for review.`), logger_default.success("Plugin submitted for review!"), logger_default.info(` Tracker issue : ${issueKey}`), logger_default.info(` Version : ${manifest.version}`), logger_default.newLine();
|
|
2528
2580
|
}
|
|
2529
2581
|
|
|
2530
2582
|
// src/utils/getVersion.ts
|
|
2531
|
-
var
|
|
2583
|
+
var import_fs14 = require("fs"), import_path13 = require("path"), UNKNOWN_VERSION = "unknown", getVersionFromPackageJson = () => {
|
|
2532
2584
|
try {
|
|
2533
|
-
let packagePath = (0,
|
|
2534
|
-
return (0,
|
|
2585
|
+
let packagePath = (0, import_path13.resolve)(__dirname, "../../package.json");
|
|
2586
|
+
return (0, import_fs14.existsSync)(packagePath) && JSON.parse((0, import_fs14.readFileSync)(packagePath, "utf-8")).version || null;
|
|
2535
2587
|
} catch {
|
|
2536
2588
|
return null;
|
|
2537
2589
|
}
|
|
2538
|
-
}, getVersion = () => "0.
|
|
2590
|
+
}, getVersion = () => "0.2.0-dev";
|
|
2539
2591
|
|
|
2540
2592
|
// src/index.ts
|
|
2541
2593
|
init_logger();
|
|
2542
|
-
|
|
2594
|
+
init_verbose();
|
|
2595
|
+
function withErrorHandling(fn) {
|
|
2543
2596
|
return async (...args) => {
|
|
2544
2597
|
try {
|
|
2545
2598
|
await fn(...args);
|
|
@@ -2550,19 +2603,21 @@ function withErrorHandling2(fn) {
|
|
|
2550
2603
|
}
|
|
2551
2604
|
async function main() {
|
|
2552
2605
|
let program = new import_commander.Command(), version = getVersion();
|
|
2553
|
-
await checkUpdate(version), program.name(CLI_NAME2).description(CLI_DESCRIPTION2).version(version), CLI_HELP_TEXT2 && program.addHelpText("before", CLI_HELP_TEXT2), program.
|
|
2606
|
+
await checkUpdate(version), program.name(CLI_NAME2).description(CLI_DESCRIPTION2).version(version), CLI_HELP_TEXT2 && program.addHelpText("before", CLI_HELP_TEXT2), program.hook("preAction", (thisCommand) => {
|
|
2607
|
+
setVerboseEnabled(!!thisCommand.opts().verbose);
|
|
2608
|
+
}), registerDistributionCommands2(program), program.command("feedback").description("Let us know what you think about Yandex Tracker plugins").action(() => {
|
|
2554
2609
|
logger_default.info(
|
|
2555
2610
|
`Help us make Yandex Tracker even better.
|
|
2556
2611
|
To report bugs or issues, go to: https://forms.yandex.ru/surveys/6767/`
|
|
2557
2612
|
);
|
|
2558
|
-
}), program.command("create").description("create your app").action(
|
|
2613
|
+
}), 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(
|
|
2559
2614
|
"start a tunnel to connect your local code with the app running in the development environment"
|
|
2560
|
-
).option("--no-lint", "skip lint validation").action((options) =>
|
|
2615
|
+
).option("--no-lint", "skip lint validation").action((options) => withErrorHandling(debug)(options)), program.command("lint").description("run TypeScript and ESLint checks").action(withErrorHandling(lint)), program.command("login").description("authenticate with Yandex Tracker").action(withErrorHandling(login)), program.command("logout").description("remove authentication credentials").action(withErrorHandling(logout)), program.command("whoami").description("display current authentication status").action(withErrorHandling(async () => await whoami())), process.env.USE_TRACKER_TO_PUBLISH ? (program.command("submit").description("build, attach archive to Tracker issue, and submit for review").action(withErrorHandling(submitTracker)), program.command("list").description("list my plugins").action(withErrorHandling(list)), program.command("info [issue-key]").description(
|
|
2616
|
+
"get detailed information about a plugin (uses manifest.trackerIssueKey if issue-key not provided)"
|
|
2617
|
+
).action(withErrorHandling(info2))) : (program.command("submit").description("create plugin, upload data, and submit for review").action(withErrorHandling(submitPlatform)), program.command("list").description("list my plugins").action(withErrorHandling(list)), program.command("info [plugin-id]").description(
|
|
2561
2618
|
"get detailed information about a plugin (uses manifest.id if plugin-id not provided)"
|
|
2562
|
-
).action(
|
|
2619
|
+
).action(withErrorHandling(infoPlatform)), program.command("versions [plugin-id]").description(
|
|
2563
2620
|
"list all versions of a plugin (uses manifest.id if plugin-id not provided)"
|
|
2564
|
-
).action(
|
|
2565
|
-
"get detailed information about a plugin (uses manifest.trackerIssueKey if issue-key not provided)"
|
|
2566
|
-
).action(withErrorHandling2(info2))), process.env.TRACKER_CLI_ADMIN && (program.command("deploy").description("build and upload plugin bundle to S3 for production").action(withErrorHandling2(deploy)), program.command("install").description("manage app installations").action(withErrorHandling2(install)), program.command("uninstall").description("uninstall app from all slots").action(withErrorHandling2(uninstall))), registerDistributionCommands2(program), await program.parseAsync(), process.exit(0);
|
|
2621
|
+
).action(withErrorHandling(versions))), process.env.TRACKER_CLI_ADMIN && (program.command("deploy").description("build and upload plugin bundle to S3 for production").action(withErrorHandling(deploy)), program.command("install").description("manage app installations").action(withErrorHandling(install)), program.command("uninstall").description("uninstall app from all slots").action(withErrorHandling(uninstall))), await program.parseAsync(), process.exit(0);
|
|
2567
2622
|
}
|
|
2568
2623
|
main();
|