bdy 1.23.2-dev → 1.23.4-dev-target-commands

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/distTs/detect-rules.json +351 -0
  2. package/distTs/package.json +3 -1
  3. package/distTs/src/api/client.js +156 -0
  4. package/distTs/src/cliIndex.js +4 -0
  5. package/distTs/src/command/artifact/list.js +1 -6
  6. package/distTs/src/command/distro/route/update.js +1 -1
  7. package/distTs/src/command/distro/update.js +9 -9
  8. package/distTs/src/command/environment/create.js +70 -0
  9. package/distTs/src/command/environment/delete.js +29 -0
  10. package/distTs/src/command/environment/get.js +48 -0
  11. package/distTs/src/command/environment/list.js +44 -0
  12. package/distTs/src/command/environment/resolve.js +22 -0
  13. package/distTs/src/command/environment/update.js +59 -0
  14. package/distTs/src/command/environment.js +20 -0
  15. package/distTs/src/command/pipeline/run/apply.js +62 -0
  16. package/distTs/src/command/target/create.js +33 -0
  17. package/distTs/src/command/target/delete.js +30 -0
  18. package/distTs/src/command/target/exec/command.js +65 -0
  19. package/distTs/src/command/target/exec/kill.js +25 -0
  20. package/distTs/src/command/target/exec/list.js +54 -0
  21. package/distTs/src/command/target/exec/logs.js +25 -0
  22. package/distTs/src/command/target/exec/status.js +41 -0
  23. package/distTs/src/command/target/exec.js +24 -0
  24. package/distTs/src/command/target/get.js +62 -0
  25. package/distTs/src/command/target/list.js +48 -0
  26. package/distTs/src/command/target/scope.js +60 -0
  27. package/distTs/src/command/target/update.js +31 -0
  28. package/distTs/src/command/target.js +22 -0
  29. package/distTs/src/command/yaml/actions/detect.js +268 -0
  30. package/distTs/src/command/yaml/actions/info.js +56 -0
  31. package/distTs/src/command/yaml/actions/list.js +70 -0
  32. package/distTs/src/command/yaml/actions/schema.js +104 -0
  33. package/distTs/src/command/yaml/actions.js +13 -0
  34. package/distTs/src/command/yaml/agents.js +88 -0
  35. package/distTs/src/command/yaml/cache.js +98 -0
  36. package/distTs/src/command/yaml/init.js +110 -0
  37. package/distTs/src/command/yaml/pipeline.js +42 -0
  38. package/distTs/src/command/yaml/render.js +83 -0
  39. package/distTs/src/command/yaml/schemaUtils.js +139 -0
  40. package/distTs/src/command/yaml/validate.js +259 -0
  41. package/distTs/src/command/yaml.js +18 -0
  42. package/distTs/src/diskCache.js +82 -0
  43. package/distTs/src/input.js +54 -0
  44. package/distTs/src/texts.js +196 -8
  45. package/distTs/src/utils.js +16 -2
  46. package/package.json +3 -1
  47. package/distTs/README.md +0 -181
  48. package/distTs/src/command/project/get.js +0 -18
  49. package/distTs/src/command/project/set.js +0 -31
  50. package/distTs/src/command/sandbox/get/yaml.js +0 -30
  51. package/distTs/src/command/vt/scrape.js +0 -193
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const utils_1 = require("../../utils");
7
+ const texts_1 = require("../../texts");
8
+ const output_1 = __importDefault(require("../../output"));
9
+ const input_1 = __importDefault(require("../../input"));
10
+ const scope_1 = require("./scope");
11
+ const commandTargetGet = (0, utils_1.newCommand)('get', texts_1.DESC_COMMAND_TARGET_GET);
12
+ commandTargetGet.option('-w, --workspace <domain>', texts_1.OPTION_REST_API_WORKSPACE);
13
+ commandTargetGet.option('-p, --project <name>', texts_1.OPTION_REST_API_PROJECT);
14
+ commandTargetGet.option('--pipeline <identifier>', texts_1.OPTION_TARGET_PIPELINE);
15
+ commandTargetGet.option('--environment <identifier>', texts_1.OPTION_TARGET_ENVIRONMENT);
16
+ commandTargetGet.option('--format <text|json>', texts_1.OPTION_FORMAT);
17
+ commandTargetGet.argument('<identifier>', texts_1.OPTION_TARGET_IDENTIFIER);
18
+ commandTargetGet.addHelpText('after', `\nEXAMPLES:${texts_1.EXAMPLE_TARGET_GET}`);
19
+ commandTargetGet.action(async (identifier, options) => {
20
+ const workspace = input_1.default.restApiWorkspace(options.workspace);
21
+ const client = input_1.default.restApiTokenClient();
22
+ const target_id = await (0, scope_1.resolveTargetId)(client, workspace, identifier, options);
23
+ const target = await client.getTarget(workspace, target_id);
24
+ if (options.format === 'json') {
25
+ output_1.default.json(target);
26
+ }
27
+ else {
28
+ const data = [
29
+ ['Field', 'Value'],
30
+ ['ID', target.id || '-'],
31
+ ['Identifier', target.identifier || '-'],
32
+ ['Name', target.name || '-'],
33
+ ['Type', target.type || '-'],
34
+ ['Scope', (0, scope_1.targetScopeOf)(target)],
35
+ ['Tags', (target.tags || []).join(', ') || '-'],
36
+ ['Note', target.note || '-'],
37
+ ['Agent note', target.agent_note || '-'],
38
+ ['Disabled', target.disabled ? 'true' : 'false'],
39
+ ];
40
+ if (target.project) {
41
+ data.push(['Project', target.project.name || '-']);
42
+ }
43
+ if (target.pipeline) {
44
+ data.push([
45
+ 'Pipeline',
46
+ target.pipeline.identifier || String(target.pipeline.id) || '-',
47
+ ]);
48
+ }
49
+ if (target.environment) {
50
+ data.push([
51
+ 'Environment',
52
+ target.environment.identifier || target.environment.id || '-',
53
+ ]);
54
+ }
55
+ if (target.html_url) {
56
+ data.push(['URL', target.html_url]);
57
+ }
58
+ output_1.default.table(data);
59
+ }
60
+ output_1.default.exitNormal();
61
+ });
62
+ exports.default = commandTargetGet;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const utils_1 = require("../../utils");
7
+ const texts_1 = require("../../texts");
8
+ const output_1 = __importDefault(require("../../output"));
9
+ const input_1 = __importDefault(require("../../input"));
10
+ const scope_1 = require("./scope");
11
+ const commandTargetList = (0, utils_1.newCommand)('list', texts_1.DESC_COMMAND_TARGET_LIST);
12
+ commandTargetList.alias('ls');
13
+ commandTargetList.option('-w, --workspace <domain>', texts_1.OPTION_REST_API_WORKSPACE);
14
+ commandTargetList.option('-p, --project <name>', texts_1.OPTION_REST_API_PROJECT);
15
+ commandTargetList.option('--pipeline <identifier>', texts_1.OPTION_TARGET_PIPELINE);
16
+ commandTargetList.option('--environment <identifier>', texts_1.OPTION_TARGET_ENVIRONMENT);
17
+ commandTargetList.option('--scope <scope>', texts_1.OPT_COMMAND_TARGET_SCOPE);
18
+ commandTargetList.option('--format <text|json>', texts_1.OPTION_FORMAT);
19
+ commandTargetList.addHelpText('after', `\nEXAMPLES:${texts_1.EXAMPLE_TARGET_LIST}`);
20
+ commandTargetList.action(async (options) => {
21
+ const workspace = input_1.default.restApiWorkspace(options.workspace);
22
+ const project = input_1.default.restApiProject(options.project, true);
23
+ const scope = input_1.default.targetScope(project, options.pipeline, options.environment, options.scope);
24
+ const client = input_1.default.restApiTokenClient();
25
+ const filters = await (0, scope_1.resolveTargetScope)(client, workspace, project, scope, options);
26
+ const result = await client.getTargets(workspace, filters);
27
+ const targets = result.targets || [];
28
+ if (options.format === 'json') {
29
+ output_1.default.json(targets);
30
+ }
31
+ else {
32
+ if (targets.length === 0) {
33
+ output_1.default.exitNormal(texts_1.TXT_TARGET_NOT_FOUND);
34
+ }
35
+ const data = [['NAME', 'IDENTIFIER', 'TYPE', 'SCOPE']];
36
+ for (const target of targets) {
37
+ data.push([
38
+ target.name || '-',
39
+ target.identifier || '-',
40
+ target.type || '-',
41
+ (0, scope_1.targetScopeOf)(target),
42
+ ]);
43
+ }
44
+ output_1.default.table(data);
45
+ }
46
+ output_1.default.exitNormal();
47
+ });
48
+ exports.default = commandTargetList;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.resolveTargetScope = exports.targetScopeOf = exports.resolveTargetId = void 0;
7
+ const utils_1 = require("../../utils");
8
+ const texts_1 = require("../../texts");
9
+ const output_1 = __importDefault(require("../../output"));
10
+ const input_1 = __importDefault(require("../../input"));
11
+ // Shared resolve preamble for commands taking a target identifier: line
12
+ // context from flags/env -> /identifiers -> hash id, exiting on a miss.
13
+ const resolveTargetId = async (client, workspace, identifier, options) => {
14
+ const project = input_1.default.restApiProject(options.project, true);
15
+ const line = input_1.default.targetLine(project, options.pipeline, options.environment);
16
+ const { target_id } = await client.getTargetByIdentifier(workspace, identifier, line);
17
+ if (!target_id) {
18
+ output_1.default.exitError(texts_1.ERR_TARGET_NOT_FOUND);
19
+ }
20
+ return target_id;
21
+ };
22
+ exports.resolveTargetId = resolveTargetId;
23
+ const targetScopeOf = (target) => {
24
+ if (target.pipeline)
25
+ return utils_1.TARGET_SCOPE.PIPELINE;
26
+ if (target.environment)
27
+ return utils_1.TARGET_SCOPE.ENVIRONMENT;
28
+ if (target.project)
29
+ return utils_1.TARGET_SCOPE.PROJECT;
30
+ return utils_1.TARGET_SCOPE.WORKSPACE;
31
+ };
32
+ exports.targetScopeOf = targetScopeOf;
33
+ // Input.targetScope guarantees project is set for the PIPELINE scope.
34
+ // Environments exist on both workspace and project level, so for the
35
+ // ENVIRONMENT scope project is optional and narrows the lookup when given.
36
+ const resolveTargetScope = async (client, workspace, project, scope, options) => {
37
+ const params = {};
38
+ if (scope === utils_1.TARGET_SCOPE.PIPELINE) {
39
+ const { pipeline_id } = await client.getPipelineByIdentifier(workspace, project, options.pipeline);
40
+ if (!pipeline_id)
41
+ output_1.default.exitError(texts_1.ERR_PIPELINE_NOT_FOUND);
42
+ params.pipelineId = pipeline_id;
43
+ }
44
+ else if (scope === utils_1.TARGET_SCOPE.ENVIRONMENT) {
45
+ const query = {
46
+ environment: options.environment,
47
+ };
48
+ if (project)
49
+ query.project = project;
50
+ const { environment_id } = await client.getResourceByIdentifier(workspace, query);
51
+ if (!environment_id)
52
+ output_1.default.exitError(texts_1.ERR_TARGET_ENVIRONMENT_NOT_FOUND);
53
+ params.environmentId = environment_id;
54
+ }
55
+ else if (scope === utils_1.TARGET_SCOPE.PROJECT) {
56
+ params.project = project;
57
+ }
58
+ return params;
59
+ };
60
+ exports.resolveTargetScope = resolveTargetScope;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const utils_1 = require("../../utils");
7
+ const texts_1 = require("../../texts");
8
+ const output_1 = __importDefault(require("../../output"));
9
+ const input_1 = __importDefault(require("../../input"));
10
+ const scope_1 = require("./scope");
11
+ const commandTargetUpdate = (0, utils_1.newCommand)('update', texts_1.DESC_COMMAND_TARGET_UPDATE);
12
+ commandTargetUpdate.alias('edit');
13
+ commandTargetUpdate.option('-w, --workspace <domain>', texts_1.OPTION_REST_API_WORKSPACE);
14
+ commandTargetUpdate.option('-p, --project <name>', texts_1.OPTION_REST_API_PROJECT);
15
+ commandTargetUpdate.option('--pipeline <identifier>', texts_1.OPTION_TARGET_PIPELINE);
16
+ commandTargetUpdate.option('--environment <identifier>', texts_1.OPTION_TARGET_ENVIRONMENT);
17
+ commandTargetUpdate.option('--yaml <content|@path>', texts_1.OPTION_TARGET_YAML);
18
+ commandTargetUpdate.argument('<identifier>', texts_1.OPTION_TARGET_IDENTIFIER);
19
+ commandTargetUpdate.addHelpText('after', `\nEXAMPLES:${texts_1.EXAMPLE_TARGET_UPDATE}`);
20
+ commandTargetUpdate.action(async (identifier, options) => {
21
+ const yaml = input_1.default.restApiYaml(options.yaml);
22
+ const workspace = input_1.default.restApiWorkspace(options.workspace);
23
+ const client = input_1.default.restApiTokenClient();
24
+ const target_id = await (0, scope_1.resolveTargetId)(client, workspace, identifier, options);
25
+ const body = {
26
+ yaml: Buffer.from(yaml, 'utf8').toString('base64'),
27
+ };
28
+ const result = await client.updateTargetByYaml(workspace, target_id, body);
29
+ output_1.default.exitSuccess((0, texts_1.TXT_TARGET_UPDATED)(result.identifier, result.html_url));
30
+ });
31
+ exports.default = commandTargetUpdate;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const utils_1 = require("../utils");
7
+ const texts_1 = require("../texts");
8
+ const list_1 = __importDefault(require("./target/list"));
9
+ const get_1 = __importDefault(require("./target/get"));
10
+ const create_1 = __importDefault(require("./target/create"));
11
+ const update_1 = __importDefault(require("./target/update"));
12
+ const delete_1 = __importDefault(require("./target/delete"));
13
+ const exec_1 = __importDefault(require("./target/exec"));
14
+ const commandTarget = (0, utils_1.newCommand)('target', texts_1.DESC_COMMAND_TARGET);
15
+ commandTarget.alias('tg');
16
+ commandTarget.addCommand(list_1.default);
17
+ commandTarget.addCommand(get_1.default);
18
+ commandTarget.addCommand(create_1.default);
19
+ commandTarget.addCommand(update_1.default);
20
+ commandTarget.addCommand(delete_1.default);
21
+ commandTarget.addCommand(exec_1.default);
22
+ exports.default = commandTarget;
@@ -0,0 +1,268 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.detectActions = detectActions;
7
+ const fs_1 = require("fs");
8
+ const path_1 = __importDefault(require("path"));
9
+ const picomatch_1 = __importDefault(require("picomatch"));
10
+ const utils_1 = require("../../../utils");
11
+ const cache_1 = require("../cache");
12
+ const DETECT_CACHE_TTL = 10 * 60 * 1000; // 10 minutes
13
+ const DETECT_CACHE_PREFIX = 'detect:';
14
+ let cachedRules = null;
15
+ function loadDetectRules() {
16
+ if (cachedRules)
17
+ return cachedRules;
18
+ const filePath = path_1.default.resolve((0, utils_1.getRootDir)(), 'detect-rules.json');
19
+ cachedRules = JSON.parse((0, fs_1.readFileSync)(filePath, 'utf8'));
20
+ return cachedRules;
21
+ }
22
+ function safeReadDir(dir) {
23
+ try {
24
+ return (0, fs_1.readdirSync)(dir, { withFileTypes: true });
25
+ }
26
+ catch {
27
+ return [];
28
+ }
29
+ }
30
+ function readDirIndex(dir) {
31
+ const names = [];
32
+ const lowerNames = new Set();
33
+ const lowerDirs = new Set();
34
+ for (const entry of safeReadDir(dir)) {
35
+ names.push(entry.name);
36
+ lowerNames.add(entry.name.toLowerCase());
37
+ if (entry.isDirectory())
38
+ lowerDirs.add(entry.name.toLowerCase());
39
+ }
40
+ return { names, lowerNames, lowerDirs };
41
+ }
42
+ function existsCaseInsensitive(dir, relPath, mustBeDir) {
43
+ const segments = relPath.split('/').filter(Boolean);
44
+ if (segments.length === 0)
45
+ return false;
46
+ let current = dir;
47
+ for (let i = 0; i < segments.length; i++) {
48
+ const lower = segments[i].toLowerCase();
49
+ const found = safeReadDir(current).find((e) => e.name.toLowerCase() === lower);
50
+ if (!found)
51
+ return false;
52
+ if (i === segments.length - 1 && mustBeDir && !found.isDirectory())
53
+ return false;
54
+ current = path_1.default.join(current, found.name);
55
+ }
56
+ return true;
57
+ }
58
+ function fileMatchesAny(patterns, dir, index) {
59
+ for (const pattern of patterns) {
60
+ if (pattern.includes('*')) {
61
+ const isMatch = (0, picomatch_1.default)(pattern, { nocase: true, dot: true });
62
+ if (index.names.some((name) => isMatch(name)))
63
+ return true;
64
+ }
65
+ else if (pattern.includes('/')) {
66
+ const mustBeDir = pattern.endsWith('/');
67
+ const rel = mustBeDir ? pattern.slice(0, -1) : pattern;
68
+ if (rel.includes('/')) {
69
+ if (existsCaseInsensitive(dir, rel, mustBeDir))
70
+ return true;
71
+ }
72
+ else if (mustBeDir) {
73
+ if (index.lowerDirs.has(rel.toLowerCase()))
74
+ return true;
75
+ }
76
+ else if (index.lowerNames.has(rel.toLowerCase())) {
77
+ return true;
78
+ }
79
+ }
80
+ else if (index.lowerNames.has(pattern.toLowerCase())) {
81
+ return true;
82
+ }
83
+ }
84
+ return false;
85
+ }
86
+ function parsePackageJson(content) {
87
+ const pkg = JSON.parse(content);
88
+ return Object.keys({ ...pkg.dependencies, ...pkg.devDependencies });
89
+ }
90
+ function parseRequirementsTxt(content) {
91
+ const names = [];
92
+ for (const line of content.split('\n')) {
93
+ const trimmed = line.trim();
94
+ if (trimmed && !trimmed.startsWith('#') && !trimmed.startsWith('-')) {
95
+ names.push(trimmed.split(/[>=<!~[;]/)[0].trim());
96
+ }
97
+ }
98
+ return names;
99
+ }
100
+ function parseComposerJson(content) {
101
+ const composer = JSON.parse(content);
102
+ return Object.keys({ ...composer.require, ...composer['require-dev'] });
103
+ }
104
+ function parseGoMod(content) {
105
+ const names = [];
106
+ const requireBlocks = content.match(/require\s*\(([\s\S]*?)\)/g);
107
+ if (requireBlocks) {
108
+ for (const block of requireBlocks) {
109
+ for (const line of block.split('\n')) {
110
+ const trimmed = line.trim();
111
+ if (trimmed && !trimmed.startsWith('//') && !trimmed.startsWith('require') && trimmed !== ')') {
112
+ names.push(trimmed.split(/\s/)[0]);
113
+ }
114
+ }
115
+ }
116
+ }
117
+ const singleReqs = content.match(/^require\s+(\S+)/gm);
118
+ if (singleReqs) {
119
+ for (const req of singleReqs)
120
+ names.push(req.replace(/^require\s+/, '').trim());
121
+ }
122
+ return names;
123
+ }
124
+ function parseGemfile(content) {
125
+ const names = [];
126
+ for (const line of content.split('\n')) {
127
+ const match = line.match(/^\s*gem\s+['"]([^'"]+)['"]/);
128
+ if (match)
129
+ names.push(match[1]);
130
+ }
131
+ return names;
132
+ }
133
+ function parsePubspec(content) {
134
+ const YAML = require('yaml');
135
+ const pubspec = YAML.parse(content) || {};
136
+ return [
137
+ ...Object.keys(pubspec.dependencies || {}),
138
+ ...Object.keys(pubspec.dev_dependencies || {}),
139
+ ];
140
+ }
141
+ function parseCargoToml(content) {
142
+ const names = [];
143
+ const depSection = content.match(/\[dependencies]([\s\S]*?)(?=\n\[|$)/);
144
+ if (depSection) {
145
+ for (const line of depSection[1].split('\n')) {
146
+ const match = line.match(/^(\S+)\s*=/);
147
+ if (match)
148
+ names.push(match[1]);
149
+ }
150
+ }
151
+ return names;
152
+ }
153
+ function parsePomXml(content) {
154
+ const names = [];
155
+ const artifacts = content.match(/<artifactId>([^<]+)<\/artifactId>/g);
156
+ if (artifacts) {
157
+ for (const a of artifacts)
158
+ names.push(a.replace(/<\/?artifactId>/g, ''));
159
+ }
160
+ return names;
161
+ }
162
+ function parseGradle(content) {
163
+ const names = [];
164
+ const deps = content.match(/(?:implementation|api|compile|testImplementation)\s*[('"]([^'"()]+)['")\s]/g);
165
+ if (deps) {
166
+ for (const d of deps) {
167
+ const match = d.match(/['"]([^'"]+)['"]/);
168
+ if (match)
169
+ names.push(match[1]);
170
+ }
171
+ }
172
+ return names;
173
+ }
174
+ function parsePyproject(content) {
175
+ const names = [];
176
+ const depMatch = content.match(/dependencies\s*=\s*\[([\s\S]*?)]/);
177
+ if (depMatch) {
178
+ const items = depMatch[1].match(/["']([^"'>=<![;]+)/g);
179
+ if (items) {
180
+ for (const item of items)
181
+ names.push(item.replace(/^["']/, '').trim());
182
+ }
183
+ }
184
+ return names;
185
+ }
186
+ const MANIFEST_PARSERS = [
187
+ { file: 'package.json', parse: parsePackageJson },
188
+ { file: 'requirements.txt', parse: parseRequirementsTxt },
189
+ { file: 'composer.json', parse: parseComposerJson },
190
+ { file: 'go.mod', parse: parseGoMod },
191
+ { file: 'Gemfile', parse: parseGemfile },
192
+ { file: 'pubspec.yaml', parse: parsePubspec },
193
+ { file: 'Cargo.toml', parse: parseCargoToml },
194
+ { file: 'pom.xml', parse: parsePomXml },
195
+ { file: 'build.gradle', parse: parseGradle },
196
+ { file: 'build.gradle.kts', parse: parseGradle },
197
+ { file: 'pyproject.toml', parse: parsePyproject },
198
+ ];
199
+ const LOCKFILES = ['package-lock.json', 'composer.lock', 'go.sum', 'Gemfile.lock', 'pubspec.lock', 'Cargo.lock'];
200
+ const MANIFEST_FILES = [...new Set(MANIFEST_PARSERS.map((p) => p.file)), ...LOCKFILES];
201
+ function readPackageNames(dir) {
202
+ const packages = new Set();
203
+ for (const { file, parse } of MANIFEST_PARSERS) {
204
+ const filePath = path_1.default.join(dir, file);
205
+ if (!(0, fs_1.existsSync)(filePath))
206
+ continue;
207
+ try {
208
+ for (const name of parse((0, fs_1.readFileSync)(filePath, 'utf8'))) {
209
+ if (name)
210
+ packages.add(name);
211
+ }
212
+ }
213
+ catch {
214
+ // ignore malformed manifests
215
+ }
216
+ }
217
+ return packages;
218
+ }
219
+ function packageMatchesPattern(pkg, pattern) {
220
+ if (pattern.endsWith('/*')) {
221
+ const prefix = pattern.slice(0, -2);
222
+ return pkg.startsWith(prefix + '/');
223
+ }
224
+ return pkg === pattern;
225
+ }
226
+ function scanActions(dir) {
227
+ const rules = loadDetectRules();
228
+ const packages = readPackageNames(dir);
229
+ const detectedTypes = [];
230
+ const index = readDirIndex(dir);
231
+ for (const [type, rule] of Object.entries(rules)) {
232
+ let matched = false;
233
+ if (rule.files) {
234
+ matched = fileMatchesAny(rule.files, dir, index);
235
+ }
236
+ if (!matched && rule.packages) {
237
+ for (const pkgPattern of rule.packages) {
238
+ for (const pkg of packages) {
239
+ if (packageMatchesPattern(pkg, pkgPattern)) {
240
+ matched = true;
241
+ break;
242
+ }
243
+ }
244
+ if (matched)
245
+ break;
246
+ }
247
+ }
248
+ if (matched) {
249
+ detectedTypes.push(type);
250
+ }
251
+ }
252
+ return detectedTypes;
253
+ }
254
+ let pruneScheduled = false;
255
+ function detectActions(dir) {
256
+ const cacheKey = DETECT_CACHE_PREFIX + dir;
257
+ const fingerprint = (0, cache_1.fingerprintFiles)(dir, MANIFEST_FILES);
258
+ const cached = (0, cache_1.getCache)(cacheKey, fingerprint);
259
+ if (cached)
260
+ return new Set(cached);
261
+ const detected = scanActions(dir);
262
+ (0, cache_1.setCache)(cacheKey, fingerprint, detected, DETECT_CACHE_TTL);
263
+ if (!pruneScheduled) {
264
+ pruneScheduled = true;
265
+ process.nextTick(() => (0, cache_1.pruneCache)());
266
+ }
267
+ return new Set(detected);
268
+ }
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const utils_1 = require("../../../utils");
7
+ const output_1 = __importDefault(require("../../../output"));
8
+ const texts_1 = require("../../../texts");
9
+ const schema_1 = require("./schema");
10
+ const schemaUtils_1 = require("../schemaUtils");
11
+ const detect_1 = require("./detect");
12
+ const render_1 = require("../render");
13
+ const commandYamlActionsInfo = (0, utils_1.newCommand)('info', texts_1.DESC_COMMAND_YAML_ACTIONS_INFO);
14
+ commandYamlActionsInfo.argument('<type>', texts_1.OPTION_ACTION_TYPE);
15
+ commandYamlActionsInfo.action(async (type) => {
16
+ await (0, schemaUtils_1.ensureYamlSchema)();
17
+ const actions = (0, schema_1.loadSchema)();
18
+ const action = (0, schema_1.findAction)(actions, type);
19
+ if (!action) {
20
+ output_1.default.error((0, texts_1.ERR_ACTION_NOT_FOUND)(type));
21
+ const suggestions = (0, schema_1.suggestActions)(actions, type);
22
+ if (suggestions.length > 0) {
23
+ output_1.default.muted((0, texts_1.TXT_ACTION_DID_YOU_MEAN)(suggestions.map((a) => `${a.type} (${a.name})`).join(', ')));
24
+ }
25
+ else {
26
+ const detectedTypes = (0, detect_1.detectActions)(process.cwd());
27
+ if (detectedTypes.size > 0) {
28
+ const detected = actions.filter((a) => detectedTypes.has(a.type)).slice(0, 5);
29
+ output_1.default.muted(`Suggested based on your repo: ${detected.map((a) => `${a.type} (${a.name})`).join(', ')}`);
30
+ }
31
+ }
32
+ output_1.default.muted(texts_1.TXT_ACTION_USE_LIST);
33
+ output_1.default.exitNormal();
34
+ return;
35
+ }
36
+ output_1.default.blue(action.name, false);
37
+ output_1.default.gray(` · ${action.type}`);
38
+ output_1.default.gray(action.description);
39
+ output_1.default.normal('');
40
+ const { common, specific } = (0, schema_1.splitProperties)(action);
41
+ if (Object.keys(specific).length > 0) {
42
+ output_1.default.blue('Type-specific fields');
43
+ (0, render_1.outputProperties)(specific, action.required);
44
+ output_1.default.normal('');
45
+ }
46
+ if (Object.keys(common).length > 0) {
47
+ output_1.default.blue('Common fields');
48
+ (0, render_1.outputProperties)(common, action.required);
49
+ }
50
+ if (action.examples.length > 0) {
51
+ output_1.default.normal('');
52
+ (0, render_1.outputExamples)(action.examples);
53
+ }
54
+ output_1.default.exitNormal();
55
+ });
56
+ exports.default = commandYamlActionsInfo;
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const utils_1 = require("../../../utils");
7
+ const output_1 = __importDefault(require("../../../output"));
8
+ const texts_1 = require("../../../texts");
9
+ const schema_1 = require("./schema");
10
+ const schemaUtils_1 = require("../schemaUtils");
11
+ const detect_1 = require("./detect");
12
+ function actionTable(actions) {
13
+ const data = [['TYPE', 'NAME', 'DESCRIPTION']];
14
+ for (const action of actions) {
15
+ const desc = action.description.length > 80
16
+ ? action.description.substring(0, 77) + '...'
17
+ : action.description;
18
+ data.push([action.type, action.name, desc]);
19
+ }
20
+ return data;
21
+ }
22
+ const commandYamlActionsList = (0, utils_1.newCommand)('list', texts_1.DESC_COMMAND_YAML_ACTIONS_LIST);
23
+ commandYamlActionsList.alias('ls');
24
+ commandYamlActionsList.option('-s, --search <query>', texts_1.OPTION_ACTION_SEARCH);
25
+ commandYamlActionsList.action(async (options) => {
26
+ await (0, schemaUtils_1.ensureYamlSchema)();
27
+ const actions = (0, schema_1.loadSchema)();
28
+ const detectedTypes = (0, detect_1.detectActions)(process.cwd());
29
+ if (options.search) {
30
+ const index = (0, schema_1.createActionIndex)(actions);
31
+ const hits = index.search(options.search);
32
+ const slugSet = new Set(hits.map((h) => h.id));
33
+ const results = actions.filter((a) => slugSet.has(a.slug));
34
+ results.sort((a, b) => {
35
+ const ai = hits.findIndex((h) => h.id === a.slug);
36
+ const bi = hits.findIndex((h) => h.id === b.slug);
37
+ return ai - bi;
38
+ });
39
+ if (results.length === 0) {
40
+ const suggestions = index.autoSuggest(options.search);
41
+ output_1.default.error((0, texts_1.ERR_ACTION_SEARCH_NO_RESULTS)(options.search));
42
+ if (suggestions.length > 0) {
43
+ output_1.default.muted((0, texts_1.TXT_ACTION_DID_YOU_MEAN)(suggestions.map((s) => s.suggestion).join(', ')));
44
+ }
45
+ if (detectedTypes.size > 0) {
46
+ const detected = actions.filter((a) => detectedTypes.has(a.type));
47
+ output_1.default.normal('');
48
+ output_1.default.blue('Suggested based on your repo');
49
+ output_1.default.table(actionTable(detected));
50
+ }
51
+ output_1.default.muted(texts_1.TXT_ACTION_USE_LIST);
52
+ output_1.default.exitNormal();
53
+ return;
54
+ }
55
+ output_1.default.table(actionTable(results));
56
+ output_1.default.exitNormal();
57
+ return;
58
+ }
59
+ const byType = (a, b) => a.type.localeCompare(b.type);
60
+ if (detectedTypes.size > 0) {
61
+ const detected = actions.filter((a) => detectedTypes.has(a.type)).sort(byType);
62
+ output_1.default.blue('Suggested');
63
+ output_1.default.table(actionTable(detected));
64
+ output_1.default.normal('');
65
+ }
66
+ output_1.default.blue(`All actions (${actions.length})`);
67
+ output_1.default.table(actionTable([...actions].sort(byType)));
68
+ output_1.default.exitNormal();
69
+ });
70
+ exports.default = commandYamlActionsList;