@meltstudio/meltctl 4.35.0 → 4.36.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  import chalk from 'chalk';
2
2
  import fs from 'fs-extra';
3
3
  import path from 'path';
4
- import { getToken, tokenFetch } from '../utils/api.js';
4
+ import { getClient } from '../utils/api.js';
5
5
  import { getGitBranch, getGitCommit, getGitRepository, getProjectName, findMdFiles, } from '../utils/git.js';
6
6
  function detectAuditType(filename) {
7
7
  const lower = filename.toLowerCase();
@@ -28,7 +28,7 @@ async function autoDetectAuditFile() {
28
28
  return null;
29
29
  }
30
30
  export async function auditSubmitCommand(file) {
31
- const token = await getToken();
31
+ const client = await getClient();
32
32
  let filePath;
33
33
  if (file) {
34
34
  filePath = path.resolve(file);
@@ -53,62 +53,33 @@ export async function auditSubmitCommand(file) {
53
53
  const branch = getGitBranch();
54
54
  const commit = getGitCommit();
55
55
  const repo = getGitRepository();
56
- const payload = {
57
- type: auditType,
58
- project,
59
- repository: repo?.slug ?? null,
60
- repositoryUrl: repo?.url ?? null,
61
- branch,
62
- commit,
63
- content,
64
- metadata: { filename },
65
- };
66
56
  try {
67
- const res = await tokenFetch(token, '/audits', {
68
- method: 'POST',
69
- headers: { 'Content-Type': 'application/json' },
70
- body: JSON.stringify(payload),
57
+ const result = await client.audits.submit({
58
+ type: auditType,
59
+ project,
60
+ repository: repo?.slug ?? null,
61
+ repositoryUrl: repo?.url ?? null,
62
+ branch,
63
+ commit,
64
+ content,
65
+ metadata: { filename },
71
66
  });
72
- if (res.ok) {
73
- const body = (await res.json());
74
- console.log(chalk.green(`\n ✓ Audit submitted! ID: ${body.id}\n`));
75
- }
76
- else {
77
- const body = (await res.json());
78
- console.error(chalk.red(`\nFailed to submit audit: ${body.error ?? res.statusText}`));
79
- process.exit(1);
80
- }
67
+ console.log(chalk.green(`\n ✓ Audit submitted! ID: ${result.id}\n`));
81
68
  }
82
69
  catch (error) {
83
- console.error(chalk.red(`Failed to submit audit: ${error instanceof Error ? error.message : 'Unknown error'}`));
70
+ console.error(chalk.red(`\nFailed to submit audit: ${error instanceof Error ? error.message : 'Unknown error'}`));
84
71
  process.exit(1);
85
72
  }
86
73
  }
87
74
  export async function auditListCommand(options) {
88
- const token = await getToken();
89
- const params = new URLSearchParams();
90
- if (options.type)
91
- params.set('type', options.type);
92
- if (options.repository)
93
- params.set('repository', options.repository);
94
- if (options.latest)
95
- params.set('latest', 'true');
96
- if (options.limit)
97
- params.set('limit', options.limit);
98
- const query = params.toString();
99
- const urlPath = `/audits${query ? `?${query}` : ''}`;
75
+ const client = await getClient();
100
76
  try {
101
- const res = await tokenFetch(token, urlPath);
102
- if (res.status === 403) {
103
- console.error(chalk.red('Access denied. Only Team Managers can list audits.'));
104
- process.exit(1);
105
- }
106
- if (!res.ok) {
107
- const body = (await res.json());
108
- console.error(chalk.red(`Failed to list audits: ${body.error ?? res.statusText}`));
109
- process.exit(1);
110
- }
111
- const body = (await res.json());
77
+ const body = await client.audits.list({
78
+ type: options.type,
79
+ repository: options.repository,
80
+ latest: options.latest,
81
+ limit: options.limit ? parseInt(options.limit, 10) : undefined,
82
+ });
112
83
  if (body.audits.length === 0) {
113
84
  console.log(chalk.dim('\n No audits found.\n'));
114
85
  return;
@@ -123,34 +94,7 @@ export async function auditListCommand(options) {
123
94
  console.log(chalk.dim(` ${'ID'.padEnd(10)} ${'TYPE'.padEnd(12)} ${'REPOSITORY'.padEnd(40)} ${'AGE'.padEnd(10)} ${'AUTHOR'.padEnd(30)} DATE`));
124
95
  console.log();
125
96
  for (const r of body.audits) {
126
- const createdAt = new Date(r.created_at ?? r.createdAt);
127
- const daysAgo = Math.floor((Date.now() - createdAt.getTime()) / (1000 * 60 * 60 * 24));
128
- const date = createdAt.toLocaleDateString('en-US', {
129
- month: 'short',
130
- day: 'numeric',
131
- year: 'numeric',
132
- });
133
- const repo = r.repository ?? r.project;
134
- const label = typeLabels[r.type] ?? r.type;
135
- const typeColor = r.type === 'ux-audit'
136
- ? chalk.yellow
137
- : r.type === 'security-audit'
138
- ? chalk.red
139
- : chalk.magenta;
140
- const ageText = daysAgo === 0 ? 'today' : `${daysAgo}d ago`;
141
- const isSecurityAudit = r.type === 'security-audit';
142
- const ageColor = isSecurityAudit
143
- ? daysAgo <= 30
144
- ? chalk.green
145
- : daysAgo <= 90
146
- ? chalk.yellow
147
- : chalk.red
148
- : daysAgo <= 7
149
- ? chalk.green
150
- : daysAgo <= 30
151
- ? chalk.yellow
152
- : chalk.red;
153
- console.log(` ${chalk.dim(r.id.slice(0, 8).padEnd(10))} ${typeColor(label.padEnd(12))} ${chalk.white(repo.padEnd(40))} ${ageColor(ageText.padEnd(10))} ${chalk.dim(r.author.padEnd(30))} ${chalk.dim(date)}`);
97
+ printLatestAuditRow(r, typeLabels);
154
98
  }
155
99
  }
156
100
  else {
@@ -159,24 +103,7 @@ export async function auditListCommand(options) {
159
103
  console.log(chalk.dim(hdr));
160
104
  console.log();
161
105
  for (const r of body.audits) {
162
- const date = new Date(r.createdAt).toLocaleDateString('en-US', {
163
- month: 'short',
164
- day: 'numeric',
165
- year: 'numeric',
166
- hour: '2-digit',
167
- minute: '2-digit',
168
- });
169
- const repo = r.repository ?? r.project;
170
- const label = typeLabels[r.type] ?? r.type;
171
- const typeColor = r.type === 'ux-audit'
172
- ? chalk.yellow
173
- : r.type === 'security-audit'
174
- ? chalk.red
175
- : chalk.magenta;
176
- console.log(` ${chalk.dim(r.id.slice(0, 8).padEnd(10))} ${typeColor(label.padEnd(12))} ${chalk.white(repo.padEnd(40))} ${chalk.dim(r.author.padEnd(30))} ${chalk.dim(date)}`);
177
- if (r.branch && r.branch !== 'main') {
178
- console.log(` ${' '.padEnd(10)} ${' '.padEnd(12)} ${chalk.dim(`branch: ${r.branch} commit: ${r.commit ?? 'N/A'}`)}`);
179
- }
106
+ printAuditRow(r, typeLabels);
180
107
  }
181
108
  }
182
109
  console.log();
@@ -186,24 +113,52 @@ export async function auditListCommand(options) {
186
113
  process.exit(1);
187
114
  }
188
115
  }
116
+ function printLatestAuditRow(r, typeLabels) {
117
+ const createdAt = new Date(r.created_at ?? r.createdAt);
118
+ const daysAgo = Math.floor((Date.now() - createdAt.getTime()) / (1000 * 60 * 60 * 24));
119
+ const date = createdAt.toLocaleDateString('en-US', {
120
+ month: 'short',
121
+ day: 'numeric',
122
+ year: 'numeric',
123
+ });
124
+ const repo = r.repository ?? r.project;
125
+ const label = typeLabels[r.type] ?? r.type;
126
+ const typeColor = r.type === 'ux-audit' ? chalk.yellow : r.type === 'security-audit' ? chalk.red : chalk.magenta;
127
+ const ageText = daysAgo === 0 ? 'today' : `${daysAgo}d ago`;
128
+ const isSecurityAudit = r.type === 'security-audit';
129
+ const ageColor = isSecurityAudit
130
+ ? daysAgo <= 30
131
+ ? chalk.green
132
+ : daysAgo <= 90
133
+ ? chalk.yellow
134
+ : chalk.red
135
+ : daysAgo <= 7
136
+ ? chalk.green
137
+ : daysAgo <= 30
138
+ ? chalk.yellow
139
+ : chalk.red;
140
+ console.log(` ${chalk.dim(r.id.slice(0, 8).padEnd(10))} ${typeColor(label.padEnd(12))} ${chalk.white(repo.padEnd(40))} ${ageColor(ageText.padEnd(10))} ${chalk.dim(r.author.padEnd(30))} ${chalk.dim(date)}`);
141
+ }
142
+ function printAuditRow(r, typeLabels) {
143
+ const date = new Date(r.createdAt).toLocaleDateString('en-US', {
144
+ month: 'short',
145
+ day: 'numeric',
146
+ year: 'numeric',
147
+ hour: '2-digit',
148
+ minute: '2-digit',
149
+ });
150
+ const repo = r.repository ?? r.project;
151
+ const label = typeLabels[r.type] ?? r.type;
152
+ const typeColor = r.type === 'ux-audit' ? chalk.yellow : r.type === 'security-audit' ? chalk.red : chalk.magenta;
153
+ console.log(` ${chalk.dim(r.id.slice(0, 8).padEnd(10))} ${typeColor(label.padEnd(12))} ${chalk.white(repo.padEnd(40))} ${chalk.dim(r.author.padEnd(30))} ${chalk.dim(date)}`);
154
+ if (r.branch && r.branch !== 'main') {
155
+ console.log(` ${' '.padEnd(10)} ${' '.padEnd(12)} ${chalk.dim(`branch: ${r.branch} commit: ${r.commit ?? 'N/A'}`)}`);
156
+ }
157
+ }
189
158
  export async function auditViewCommand(id, options) {
190
- const token = await getToken();
159
+ const client = await getClient();
191
160
  try {
192
- const res = await tokenFetch(token, `/audits/${id}`);
193
- if (res.status === 403) {
194
- console.error(chalk.red('Access denied. Only Team Managers can view audits.'));
195
- process.exit(1);
196
- }
197
- if (res.status === 404) {
198
- console.error(chalk.red(`Audit not found: ${id}`));
199
- process.exit(1);
200
- }
201
- if (!res.ok) {
202
- const body = (await res.json());
203
- console.error(chalk.red(`Failed to fetch audit: ${body.error ?? res.statusText}`));
204
- process.exit(1);
205
- }
206
- const audit = (await res.json());
161
+ const audit = await client.audits.get(id);
207
162
  if (options.output) {
208
163
  const outputPath = path.resolve(options.output);
209
164
  await fs.ensureDir(path.dirname(outputPath));