@valbuild/cli 0.92.1 → 0.94.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli/dist/valbuild-cli-cli.cjs.dev.js +415 -160
- package/cli/dist/valbuild-cli-cli.cjs.prod.js +415 -160
- package/cli/dist/valbuild-cli-cli.esm.js +413 -158
- package/package.json +5 -5
- package/src/__fixtures__/basic/content/basic-errors.val.ts +7 -0
- package/src/__fixtures__/basic/content/basic-files.val.ts +14 -0
- package/src/__fixtures__/basic/content/basic-gallery-2.val.ts +17 -0
- package/src/__fixtures__/basic/content/basic-gallery-fail-on-non-unique-dir.val.ts +17 -0
- package/src/__fixtures__/basic/content/basic-gallery-missing-tracked.val.ts +17 -0
- package/src/__fixtures__/basic/content/basic-gallery-wrong-metadata.val.ts +17 -0
- package/src/__fixtures__/basic/content/basic-gallery.val.ts +18 -0
- package/src/__fixtures__/basic/content/basic-image-from-galleries.val.ts +15 -0
- package/src/__fixtures__/basic/content/basic-image-from-gallery.val.ts +12 -0
- package/src/__fixtures__/basic/content/basic-image.val.ts +7 -0
- package/src/__fixtures__/basic/content/basic-valid.val.ts +7 -0
- package/src/__fixtures__/basic/public/val/files/tracked.txt +1 -0
- package/src/__fixtures__/basic/public/val/files/untracked.txt +1 -0
- package/src/__fixtures__/basic/public/val/image.png +0 -0
- package/src/__fixtures__/basic/public/val/images/image.png +0 -0
- package/src/__fixtures__/basic/public/val/images2/image.png +0 -0
- package/src/__fixtures__/basic/public/val/images3/image.png +0 -0
- package/src/__fixtures__/basic/tsconfig.json +12 -0
- package/src/__fixtures__/basic/val.config.ts +5 -0
- package/src/runValidation.test.ts +386 -0
- package/src/runValidation.ts +1096 -0
- package/src/validate.ts +131 -887
|
@@ -3,17 +3,17 @@
|
|
|
3
3
|
var meow = require('meow');
|
|
4
4
|
var chalk = require('chalk');
|
|
5
5
|
var path = require('path');
|
|
6
|
-
var
|
|
7
|
-
var core = require('@valbuild/core');
|
|
8
|
-
var internal = require('@valbuild/shared/internal');
|
|
9
|
-
var fastGlob = require('fast-glob');
|
|
10
|
-
var picocolors = require('picocolors');
|
|
6
|
+
var pc = require('picocolors');
|
|
11
7
|
var fs = require('fs/promises');
|
|
8
|
+
var fastGlob = require('fast-glob');
|
|
9
|
+
var core = require('@valbuild/core');
|
|
10
|
+
var server = require('@valbuild/server');
|
|
12
11
|
var vm = require('node:vm');
|
|
13
12
|
var ts = require('typescript');
|
|
14
13
|
var z = require('zod');
|
|
15
14
|
var node_module = require('node:module');
|
|
16
|
-
var
|
|
15
|
+
var internal = require('@valbuild/shared/internal');
|
|
16
|
+
var nodeFs = require('fs');
|
|
17
17
|
|
|
18
18
|
function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
|
|
19
19
|
|
|
@@ -38,12 +38,12 @@ function _interopNamespace(e) {
|
|
|
38
38
|
var meow__default = /*#__PURE__*/_interopDefault(meow);
|
|
39
39
|
var chalk__default = /*#__PURE__*/_interopDefault(chalk);
|
|
40
40
|
var path__default = /*#__PURE__*/_interopDefault(path);
|
|
41
|
-
var
|
|
41
|
+
var pc__default = /*#__PURE__*/_interopDefault(pc);
|
|
42
42
|
var fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
43
43
|
var vm__default = /*#__PURE__*/_interopDefault(vm);
|
|
44
44
|
var ts__default = /*#__PURE__*/_interopDefault(ts);
|
|
45
45
|
var z__default = /*#__PURE__*/_interopDefault(z);
|
|
46
|
-
var
|
|
46
|
+
var nodeFs__default = /*#__PURE__*/_interopDefault(nodeFs);
|
|
47
47
|
|
|
48
48
|
function error(message) {
|
|
49
49
|
console.error(chalk__default["default"].red("❌Error: ") + message);
|
|
@@ -130,6 +130,7 @@ const textEncoder = new TextEncoder();
|
|
|
130
130
|
|
|
131
131
|
// Handler functions
|
|
132
132
|
async function handleFileMetadata(ctx) {
|
|
133
|
+
var _fileSource$source;
|
|
133
134
|
const [, modulePath] = core.Internal.splitModuleFilePathAndModulePath(ctx.sourcePath);
|
|
134
135
|
if (!ctx.valModule.source || !ctx.valModule.schema) {
|
|
135
136
|
return {
|
|
@@ -138,24 +139,21 @@ async function handleFileMetadata(ctx) {
|
|
|
138
139
|
};
|
|
139
140
|
}
|
|
140
141
|
const fileSource = core.Internal.resolvePath(modulePath, ctx.valModule.source, ctx.valModule.schema);
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
errorMessage: `Expected file to be defined at: ${ctx.sourcePath} but no file was found`
|
|
157
|
-
};
|
|
158
|
-
}
|
|
142
|
+
|
|
143
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
144
|
+
const fileRefProp = (_fileSource$source = fileSource.source) === null || _fileSource$source === void 0 ? void 0 : _fileSource$source[core.FILE_REF_PROP];
|
|
145
|
+
if (!fileRefProp) {
|
|
146
|
+
return {
|
|
147
|
+
success: false,
|
|
148
|
+
errorMessage: `Expected file to be defined at: ${ctx.sourcePath} but no file was found`
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
const filePath = path__default["default"].join(ctx.projectRoot, fileRefProp);
|
|
152
|
+
if (!ctx.fs.fileExists(filePath)) {
|
|
153
|
+
return {
|
|
154
|
+
success: false,
|
|
155
|
+
errorMessage: `File ${filePath} does not exist`
|
|
156
|
+
};
|
|
159
157
|
}
|
|
160
158
|
return {
|
|
161
159
|
success: true,
|
|
@@ -197,7 +195,7 @@ async function handleKeyOfCheck(ctx) {
|
|
|
197
195
|
};
|
|
198
196
|
}
|
|
199
197
|
async function handleRemoteFileUpload(ctx) {
|
|
200
|
-
var
|
|
198
|
+
var _resolvedRemoteFileAt;
|
|
201
199
|
if (!ctx.fix) {
|
|
202
200
|
return {
|
|
203
201
|
success: false,
|
|
@@ -212,35 +210,37 @@ async function handleRemoteFileUpload(ctx) {
|
|
|
212
210
|
};
|
|
213
211
|
}
|
|
214
212
|
const resolvedRemoteFileAtSourcePath = core.Internal.resolvePath(modulePath, ctx.valModule.source, ctx.valModule.schema);
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
errorMessage: `Expected file to be defined at: ${ctx.sourcePath} but no file was found`
|
|
231
|
-
};
|
|
232
|
-
}
|
|
213
|
+
|
|
214
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
215
|
+
const fileRefProp = (_resolvedRemoteFileAt = resolvedRemoteFileAtSourcePath.source) === null || _resolvedRemoteFileAt === void 0 ? void 0 : _resolvedRemoteFileAt[core.FILE_REF_PROP];
|
|
216
|
+
if (!fileRefProp) {
|
|
217
|
+
return {
|
|
218
|
+
success: false,
|
|
219
|
+
errorMessage: `Expected file to be defined at: ${ctx.sourcePath} but no file was found`
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
const filePath = path__default["default"].join(ctx.projectRoot, fileRefProp);
|
|
223
|
+
if (!ctx.fs.fileExists(filePath)) {
|
|
224
|
+
return {
|
|
225
|
+
success: false,
|
|
226
|
+
errorMessage: `File ${filePath} does not exist`
|
|
227
|
+
};
|
|
233
228
|
}
|
|
234
229
|
const patFile = server.getPersonalAccessTokenPath(ctx.projectRoot);
|
|
235
|
-
|
|
236
|
-
await fs__default["default"].access(patFile);
|
|
237
|
-
} catch {
|
|
230
|
+
if (!ctx.fs.fileExists(patFile)) {
|
|
238
231
|
return {
|
|
239
232
|
success: false,
|
|
240
233
|
errorMessage: `File: ${path__default["default"].join(ctx.projectRoot, ctx.file)} has remote images that are not uploaded and you are not logged in.\n\nFix this error by logging in:\n\t"npx val login"\n`
|
|
241
234
|
};
|
|
242
235
|
}
|
|
243
|
-
const
|
|
236
|
+
const patFileContent = ctx.fs.readFile(patFile);
|
|
237
|
+
if (patFileContent === undefined) {
|
|
238
|
+
return {
|
|
239
|
+
success: false,
|
|
240
|
+
errorMessage: `Could not read personal access token file at ${patFile}`
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
const parsedPatFile = server.parsePersonalAccessTokenFile(patFileContent);
|
|
244
244
|
if (!parsedPatFile.success) {
|
|
245
245
|
return {
|
|
246
246
|
success: false,
|
|
@@ -251,9 +251,12 @@ async function handleRemoteFileUpload(ctx) {
|
|
|
251
251
|
pat
|
|
252
252
|
} = parsedPatFile.data;
|
|
253
253
|
if (ctx.remoteFiles[ctx.sourcePath]) {
|
|
254
|
-
console.log(picocolors__default["default"].yellow("⚠"), `Remote file ${filePath} already uploaded`);
|
|
255
254
|
return {
|
|
256
|
-
success: true
|
|
255
|
+
success: true,
|
|
256
|
+
events: [{
|
|
257
|
+
type: "remote-already-uploaded",
|
|
258
|
+
filePath
|
|
259
|
+
}]
|
|
257
260
|
};
|
|
258
261
|
}
|
|
259
262
|
if (!resolvedRemoteFileAtSourcePath.schema) {
|
|
@@ -271,22 +274,18 @@ async function handleRemoteFileUpload(ctx) {
|
|
|
271
274
|
errorMessage: `Could not resolve schema for remote file: ${ctx.sourcePath}`
|
|
272
275
|
};
|
|
273
276
|
}
|
|
277
|
+
const projectName = ctx.project;
|
|
274
278
|
let publicProjectId = ctx.publicProjectId;
|
|
275
279
|
let remoteFileBuckets = ctx.remoteFileBuckets;
|
|
276
280
|
let remoteFilesCounter = ctx.remoteFilesCounter;
|
|
277
281
|
if (!publicProjectId || !remoteFileBuckets) {
|
|
278
|
-
let projectName = process.env.VAL_PROJECT;
|
|
279
|
-
if (!projectName) {
|
|
280
|
-
var _ctx$valConfigFile;
|
|
281
|
-
projectName = (_ctx$valConfigFile = ctx.valConfigFile) === null || _ctx$valConfigFile === void 0 ? void 0 : _ctx$valConfigFile.project;
|
|
282
|
-
}
|
|
283
282
|
if (!projectName) {
|
|
284
283
|
return {
|
|
285
284
|
success: false,
|
|
286
|
-
errorMessage: "Project name not found.
|
|
285
|
+
errorMessage: "Project name not found. Add project name to val.config or set the VAL_PROJECT environment variable"
|
|
287
286
|
};
|
|
288
287
|
}
|
|
289
|
-
const settingsRes = await
|
|
288
|
+
const settingsRes = await ctx.remote.getSettings(projectName, {
|
|
290
289
|
pat
|
|
291
290
|
});
|
|
292
291
|
if (!settingsRes.success) {
|
|
@@ -304,7 +303,7 @@ async function handleRemoteFileUpload(ctx) {
|
|
|
304
303
|
errorMessage: "Could not get public project id"
|
|
305
304
|
};
|
|
306
305
|
}
|
|
307
|
-
if (!
|
|
306
|
+
if (!projectName) {
|
|
308
307
|
return {
|
|
309
308
|
success: false,
|
|
310
309
|
errorMessage: `Could not get project. Check that your val.config has the 'project' field set, or set it using the VAL_PROJECT environment variable`
|
|
@@ -324,13 +323,11 @@ async function handleRemoteFileUpload(ctx) {
|
|
|
324
323
|
errorMessage: `Internal error: could not allocate a bucket for the remote file located at ${ctx.sourcePath}`
|
|
325
324
|
};
|
|
326
325
|
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
fileBuffer = await fs__default["default"].readFile(filePath);
|
|
330
|
-
} catch (e) {
|
|
326
|
+
const fileBuffer = ctx.fs.readBuffer(filePath);
|
|
327
|
+
if (fileBuffer === undefined) {
|
|
331
328
|
return {
|
|
332
329
|
success: false,
|
|
333
|
-
errorMessage: `Error reading file: ${
|
|
330
|
+
errorMessage: `Error reading file: ${filePath}`
|
|
334
331
|
};
|
|
335
332
|
}
|
|
336
333
|
const relativeFilePath = path__default["default"].relative(ctx.projectRoot, filePath).split(path__default["default"].sep).join("/");
|
|
@@ -345,7 +342,7 @@ async function handleRemoteFileUpload(ctx) {
|
|
|
345
342
|
const fileExt = getFileExt(filePath);
|
|
346
343
|
const schema = resolveRemoteFileSchema;
|
|
347
344
|
const metadata = fileSourceMetadata;
|
|
348
|
-
const ref = core.Internal.remote.createRemoteRef(ctx.
|
|
345
|
+
const ref = core.Internal.remote.createRemoteRef(ctx.remote.remoteHost, {
|
|
349
346
|
publicProjectId,
|
|
350
347
|
coreVersion,
|
|
351
348
|
bucket,
|
|
@@ -353,8 +350,7 @@ async function handleRemoteFileUpload(ctx) {
|
|
|
353
350
|
fileHash,
|
|
354
351
|
filePath: relativeFilePath
|
|
355
352
|
});
|
|
356
|
-
|
|
357
|
-
const remoteFileUpload = await server.uploadRemoteFile(ctx.contentHostUrl, ctx.valConfigFile.project, bucket, fileHash, fileExt, fileBuffer, {
|
|
353
|
+
const remoteFileUpload = await ctx.remote.uploadFile(projectName, bucket, fileHash, fileExt, fileBuffer, {
|
|
358
354
|
pat
|
|
359
355
|
});
|
|
360
356
|
if (!remoteFileUpload.success) {
|
|
@@ -363,7 +359,6 @@ async function handleRemoteFileUpload(ctx) {
|
|
|
363
359
|
errorMessage: `Could not upload remote file: '${ref}'. Error: ${remoteFileUpload.error}`
|
|
364
360
|
};
|
|
365
361
|
}
|
|
366
|
-
console.log(picocolors__default["default"].green("✔"), `Completed upload of remote file: '${ref}'`);
|
|
367
362
|
ctx.remoteFiles[ctx.sourcePath] = {
|
|
368
363
|
ref,
|
|
369
364
|
metadata: fileSourceMetadata
|
|
@@ -373,15 +368,25 @@ async function handleRemoteFileUpload(ctx) {
|
|
|
373
368
|
shouldApplyPatch: true,
|
|
374
369
|
publicProjectId,
|
|
375
370
|
remoteFileBuckets,
|
|
376
|
-
remoteFilesCounter
|
|
371
|
+
remoteFilesCounter,
|
|
372
|
+
events: [{
|
|
373
|
+
type: "remote-uploading",
|
|
374
|
+
ref
|
|
375
|
+
}, {
|
|
376
|
+
type: "remote-uploaded",
|
|
377
|
+
ref
|
|
378
|
+
}]
|
|
377
379
|
};
|
|
378
380
|
}
|
|
379
381
|
async function handleRemoteFileDownload(ctx) {
|
|
380
382
|
if (ctx.fix) {
|
|
381
|
-
console.log(picocolors__default["default"].yellow("⚠"), `Downloading remote file in ${ctx.sourcePath}...`);
|
|
382
383
|
return {
|
|
383
384
|
success: true,
|
|
384
|
-
shouldApplyPatch: true
|
|
385
|
+
shouldApplyPatch: true,
|
|
386
|
+
events: [{
|
|
387
|
+
type: "remote-downloading",
|
|
388
|
+
sourcePath: ctx.sourcePath
|
|
389
|
+
}]
|
|
385
390
|
};
|
|
386
391
|
} else {
|
|
387
392
|
return {
|
|
@@ -546,6 +551,103 @@ async function handleRouteCheck(ctx) {
|
|
|
546
551
|
success: true
|
|
547
552
|
};
|
|
548
553
|
}
|
|
554
|
+
async function handleUniqueFolderCheck(ctx) {
|
|
555
|
+
const value = ctx.validationError.value;
|
|
556
|
+
if (!value || typeof value.directory !== "string") {
|
|
557
|
+
return {
|
|
558
|
+
success: false,
|
|
559
|
+
errorMessage: `Unexpected value in unique folder check for ${ctx.sourcePath}`
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
const {
|
|
563
|
+
directory
|
|
564
|
+
} = value;
|
|
565
|
+
const conflicts = [];
|
|
566
|
+
for (const file of ctx.valFiles) {
|
|
567
|
+
const otherModuleFilePath = `/${file}`;
|
|
568
|
+
if (otherModuleFilePath === ctx.moduleFilePath) continue;
|
|
569
|
+
const otherModule = await ctx.service.get(otherModuleFilePath, "", {
|
|
570
|
+
source: false,
|
|
571
|
+
schema: true,
|
|
572
|
+
validate: false
|
|
573
|
+
});
|
|
574
|
+
const schema = otherModule.schema;
|
|
575
|
+
if ((schema === null || schema === void 0 ? void 0 : schema.type) === "record" && schema.directory === directory && schema.mediaType) {
|
|
576
|
+
conflicts.push(otherModuleFilePath);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
if (conflicts.length > 0) {
|
|
580
|
+
return {
|
|
581
|
+
success: false,
|
|
582
|
+
errorMessage: `Gallery directory '${directory}' in ${ctx.moduleFilePath} is also used by: ${conflicts.join(", ")}. Each gallery must use a unique directory.`
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
return {
|
|
586
|
+
success: true
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
async function handleCheckAllFiles(ctx) {
|
|
590
|
+
const value = ctx.validationError.value;
|
|
591
|
+
if (!value || typeof value.directory !== "string") {
|
|
592
|
+
return {
|
|
593
|
+
success: false,
|
|
594
|
+
errorMessage: `Unexpected value in check-all-files for ${ctx.sourcePath}`
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
const {
|
|
598
|
+
directory
|
|
599
|
+
} = value;
|
|
600
|
+
const source = ctx.valModule.source;
|
|
601
|
+
if (!source || typeof source !== "object" || Array.isArray(source)) {
|
|
602
|
+
return {
|
|
603
|
+
success: false,
|
|
604
|
+
errorMessage: `Could not get source for ${ctx.sourcePath}`
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
const trackedFiles = new Set(Object.keys(source));
|
|
608
|
+
|
|
609
|
+
// Check that all tracked files exist on disk
|
|
610
|
+
const missingTrackedFiles = [...trackedFiles].filter(f => {
|
|
611
|
+
return !ctx.fs.fileExists(path__default["default"].join(ctx.projectRoot, f));
|
|
612
|
+
});
|
|
613
|
+
if (missingTrackedFiles.length > 0) {
|
|
614
|
+
if (!ctx.fix) {
|
|
615
|
+
return {
|
|
616
|
+
success: false,
|
|
617
|
+
errorMessage: `Gallery in ${ctx.moduleFilePath} has tracked files that do not exist on disk: ${missingTrackedFiles.join(", ")}. Add the files or remove them from the gallery.`
|
|
618
|
+
};
|
|
619
|
+
}
|
|
620
|
+
// fix: true — let createFixPatch remove the missing entries
|
|
621
|
+
return {
|
|
622
|
+
success: true,
|
|
623
|
+
shouldApplyPatch: true
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
const dirPath = path__default["default"].join(ctx.projectRoot, directory);
|
|
627
|
+
const filesInDir = [];
|
|
628
|
+
try {
|
|
629
|
+
const entries = ctx.fs.readDirectory(dirPath, undefined, undefined, ["**/*"]);
|
|
630
|
+
for (const entry of entries) {
|
|
631
|
+
const relPath = "/" + path__default["default"].relative(ctx.projectRoot, entry).split(path__default["default"].sep).join("/");
|
|
632
|
+
filesInDir.push(relPath);
|
|
633
|
+
}
|
|
634
|
+
} catch {
|
|
635
|
+
// directory doesn't exist — no untracked files possible
|
|
636
|
+
}
|
|
637
|
+
const untrackedFiles = filesInDir.filter(f => !trackedFiles.has(f));
|
|
638
|
+
if (untrackedFiles.length > 0) {
|
|
639
|
+
return {
|
|
640
|
+
success: false,
|
|
641
|
+
errorMessage: `Gallery in ${ctx.moduleFilePath} has files not tracked: ${untrackedFiles.join(", ")}. Add these files to the gallery or remove them from the directory.`
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
// All files accounted for — trigger metadata verification via createFixPatch
|
|
646
|
+
return {
|
|
647
|
+
success: true,
|
|
648
|
+
shouldApplyPatch: true
|
|
649
|
+
};
|
|
650
|
+
}
|
|
549
651
|
|
|
550
652
|
// Fix handler registry
|
|
551
653
|
const currentFixHandlers = {
|
|
@@ -560,7 +662,13 @@ const currentFixHandlers = {
|
|
|
560
662
|
"image:download-remote": handleRemoteFileDownload,
|
|
561
663
|
"file:download-remote": handleRemoteFileDownload,
|
|
562
664
|
"image:check-remote": handleRemoteFileCheck,
|
|
563
|
-
"
|
|
665
|
+
"images:check-remote": handleRemoteFileCheck,
|
|
666
|
+
"file:check-remote": handleRemoteFileCheck,
|
|
667
|
+
"files:check-remote": handleRemoteFileCheck,
|
|
668
|
+
"images:check-unique-folder": handleUniqueFolderCheck,
|
|
669
|
+
"files:check-unique-folder": handleUniqueFolderCheck,
|
|
670
|
+
"images:check-all-files": handleCheckAllFiles,
|
|
671
|
+
"files:check-all-files": handleCheckAllFiles
|
|
564
672
|
};
|
|
565
673
|
const deprecatedFixHandlers = {
|
|
566
674
|
"image:replace-metadata": handleFileMetadata
|
|
@@ -569,30 +677,36 @@ const fixHandlers = {
|
|
|
569
677
|
...deprecatedFixHandlers,
|
|
570
678
|
...currentFixHandlers
|
|
571
679
|
};
|
|
572
|
-
|
|
680
|
+
function createDefaultValFSHost() {
|
|
681
|
+
return {
|
|
682
|
+
...ts__default["default"].sys,
|
|
683
|
+
writeFile: (fileName, data, encoding) => {
|
|
684
|
+
nodeFs__default["default"].mkdirSync(path__default["default"].dirname(fileName), {
|
|
685
|
+
recursive: true
|
|
686
|
+
});
|
|
687
|
+
nodeFs__default["default"].writeFileSync(fileName, typeof data === "string" ? data : new Uint8Array(data), encoding);
|
|
688
|
+
},
|
|
689
|
+
rmFile: nodeFs__default["default"].rmSync,
|
|
690
|
+
readBuffer: fileName => {
|
|
691
|
+
try {
|
|
692
|
+
return nodeFs__default["default"].readFileSync(fileName);
|
|
693
|
+
} catch {
|
|
694
|
+
return undefined;
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
};
|
|
698
|
+
}
|
|
699
|
+
async function* runValidation({
|
|
573
700
|
root,
|
|
574
|
-
fix
|
|
701
|
+
fix,
|
|
702
|
+
valFiles,
|
|
703
|
+
project,
|
|
704
|
+
remote,
|
|
705
|
+
fs
|
|
575
706
|
}) {
|
|
576
|
-
const
|
|
577
|
-
const
|
|
578
|
-
const projectRoot = root ? path__default["default"].resolve(root) : process.cwd();
|
|
579
|
-
const valConfigFile = (await evalValConfigFile(projectRoot, "val.config.ts")) || (await evalValConfigFile(projectRoot, "val.config.js"));
|
|
580
|
-
console.log(picocolors__default["default"].greenBright(`Validating project${valConfigFile !== null && valConfigFile !== void 0 && valConfigFile.project ? ` '${picocolors__default["default"].inverse(valConfigFile === null || valConfigFile === void 0 ? void 0 : valConfigFile.project)}'` : ""}...`));
|
|
581
|
-
const service = await server.createService(projectRoot, {});
|
|
582
|
-
let prettier;
|
|
583
|
-
try {
|
|
584
|
-
prettier = (await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('prettier')); })).default;
|
|
585
|
-
} catch {
|
|
586
|
-
console.log("Prettier not found, skipping formatting");
|
|
587
|
-
}
|
|
588
|
-
const valFiles = await fastGlob.glob("**/*.val.{js,ts}", {
|
|
589
|
-
ignore: ["node_modules/**"],
|
|
590
|
-
cwd: projectRoot
|
|
591
|
-
});
|
|
707
|
+
const projectRoot = path__default["default"].resolve(root);
|
|
708
|
+
const service = await server.createService(projectRoot, {}, fs);
|
|
592
709
|
let errors = 0;
|
|
593
|
-
console.log(picocolors__default["default"].greenBright(`Found ${valFiles.length} files...`));
|
|
594
|
-
let publicProjectId;
|
|
595
|
-
let didFix = false;
|
|
596
710
|
|
|
597
711
|
// Create caches that persist across all file validations
|
|
598
712
|
const keyOfCache = new Map();
|
|
@@ -600,7 +714,7 @@ async function validate({
|
|
|
600
714
|
loaded: false,
|
|
601
715
|
modules: {}
|
|
602
716
|
};
|
|
603
|
-
async function validateFile(file) {
|
|
717
|
+
async function* validateFile(file) {
|
|
604
718
|
const moduleFilePath = `/${file}`; // TODO: check if this always works? (Windows?)
|
|
605
719
|
const start = Date.now();
|
|
606
720
|
const valModule = await service.get(moduleFilePath, "", {
|
|
@@ -612,10 +726,14 @@ async function validate({
|
|
|
612
726
|
let remoteFileBuckets = undefined;
|
|
613
727
|
let remoteFilesCounter = 0;
|
|
614
728
|
if (!valModule.errors) {
|
|
615
|
-
|
|
616
|
-
|
|
729
|
+
yield {
|
|
730
|
+
type: "file-valid",
|
|
731
|
+
file: moduleFilePath,
|
|
732
|
+
durationMs: Date.now() - start
|
|
733
|
+
};
|
|
734
|
+
return;
|
|
617
735
|
} else {
|
|
618
|
-
let
|
|
736
|
+
let fileErrors = 0;
|
|
619
737
|
let fixedErrors = 0;
|
|
620
738
|
if (valModule.errors) {
|
|
621
739
|
if (valModule.errors.validation) {
|
|
@@ -623,8 +741,12 @@ async function validate({
|
|
|
623
741
|
for (const v of validationErrors) {
|
|
624
742
|
if (!v.fixes || v.fixes.length === 0) {
|
|
625
743
|
// No fixes available - just report error
|
|
626
|
-
|
|
627
|
-
|
|
744
|
+
fileErrors += 1;
|
|
745
|
+
yield {
|
|
746
|
+
type: "validation-error",
|
|
747
|
+
sourcePath,
|
|
748
|
+
message: v.message
|
|
749
|
+
};
|
|
628
750
|
continue;
|
|
629
751
|
}
|
|
630
752
|
|
|
@@ -632,8 +754,12 @@ async function validate({
|
|
|
632
754
|
const fixType = v.fixes[0]; // Take first fix
|
|
633
755
|
const handler = fixHandlers[fixType];
|
|
634
756
|
if (!handler) {
|
|
635
|
-
|
|
636
|
-
|
|
757
|
+
yield {
|
|
758
|
+
type: "unknown-fix",
|
|
759
|
+
sourcePath,
|
|
760
|
+
fixes: v.fixes
|
|
761
|
+
};
|
|
762
|
+
fileErrors += 1;
|
|
637
763
|
continue;
|
|
638
764
|
}
|
|
639
765
|
|
|
@@ -648,21 +774,25 @@ async function validate({
|
|
|
648
774
|
valFiles,
|
|
649
775
|
moduleFilePath,
|
|
650
776
|
file,
|
|
777
|
+
fs,
|
|
651
778
|
remoteFiles,
|
|
652
|
-
publicProjectId,
|
|
779
|
+
publicProjectId: undefined,
|
|
653
780
|
remoteFileBuckets,
|
|
654
781
|
remoteFilesCounter,
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
valConfigFile: valConfigFile ?? undefined,
|
|
782
|
+
remote,
|
|
783
|
+
project,
|
|
658
784
|
keyOfCache,
|
|
659
785
|
routerModulesCache
|
|
660
786
|
});
|
|
661
787
|
|
|
662
|
-
//
|
|
663
|
-
if (result.
|
|
664
|
-
|
|
788
|
+
// Yield any events from handler
|
|
789
|
+
if (result.events) {
|
|
790
|
+
for (const event of result.events) {
|
|
791
|
+
yield event;
|
|
792
|
+
}
|
|
665
793
|
}
|
|
794
|
+
|
|
795
|
+
// Update shared state from handler result
|
|
666
796
|
if (result.remoteFileBuckets !== undefined) {
|
|
667
797
|
remoteFileBuckets = result.remoteFileBuckets;
|
|
668
798
|
}
|
|
@@ -670,69 +800,98 @@ async function validate({
|
|
|
670
800
|
remoteFilesCounter = result.remoteFilesCounter;
|
|
671
801
|
}
|
|
672
802
|
if (!result.success) {
|
|
673
|
-
|
|
674
|
-
|
|
803
|
+
yield {
|
|
804
|
+
type: "validation-error",
|
|
805
|
+
sourcePath,
|
|
806
|
+
message: result.errorMessage ?? "Unknown error"
|
|
807
|
+
};
|
|
808
|
+
fileErrors += 1;
|
|
675
809
|
continue;
|
|
676
810
|
}
|
|
677
811
|
|
|
678
812
|
// Apply patch if needed
|
|
679
813
|
if (result.shouldApplyPatch) {
|
|
680
|
-
var _fixPatch$remainingEr;
|
|
681
814
|
const fixPatch = await server.createFixPatch({
|
|
682
815
|
projectRoot,
|
|
683
|
-
remoteHost:
|
|
816
|
+
remoteHost: remote.remoteHost
|
|
684
817
|
}, !!fix, sourcePath, v, remoteFiles, valModule.source, valModule.schema);
|
|
685
818
|
if (fix && fixPatch !== null && fixPatch !== void 0 && fixPatch.patch && (fixPatch === null || fixPatch === void 0 ? void 0 : fixPatch.patch.length) > 0) {
|
|
686
819
|
await service.patch(moduleFilePath, fixPatch.patch);
|
|
687
|
-
didFix = true;
|
|
688
820
|
fixedErrors += 1;
|
|
689
|
-
|
|
821
|
+
yield {
|
|
822
|
+
type: "fix-applied",
|
|
823
|
+
file,
|
|
824
|
+
sourcePath
|
|
825
|
+
};
|
|
826
|
+
} else if (!fix && fixPatch !== null && fixPatch !== void 0 && fixPatch.patch && (fixPatch === null || fixPatch === void 0 ? void 0 : fixPatch.patch.length) > 0) {
|
|
827
|
+
fileErrors += 1;
|
|
828
|
+
yield {
|
|
829
|
+
type: "validation-fixable-error",
|
|
830
|
+
sourcePath,
|
|
831
|
+
message: v.message,
|
|
832
|
+
fixable: true
|
|
833
|
+
};
|
|
834
|
+
}
|
|
835
|
+
for (const e of (fixPatch === null || fixPatch === void 0 ? void 0 : fixPatch.remainingErrors) ?? []) {
|
|
836
|
+
fileErrors += 1;
|
|
837
|
+
yield {
|
|
838
|
+
type: "validation-fixable-error",
|
|
839
|
+
sourcePath,
|
|
840
|
+
message: e.message,
|
|
841
|
+
fixable: !!(e.fixes && e.fixes.length)
|
|
842
|
+
};
|
|
690
843
|
}
|
|
691
|
-
fixPatch === null || fixPatch === void 0 || (_fixPatch$remainingEr = fixPatch.remainingErrors) === null || _fixPatch$remainingEr === void 0 || _fixPatch$remainingEr.forEach(e => {
|
|
692
|
-
errors += 1;
|
|
693
|
-
console.log(e.fixes && e.fixes.length ? picocolors__default["default"].yellow("⚠") : picocolors__default["default"].red("✘"), `Got ${e.fixes && e.fixes.length ? "fixable " : ""}error in`, `${sourcePath}:`, e.message);
|
|
694
|
-
});
|
|
695
844
|
}
|
|
696
845
|
}
|
|
697
846
|
}
|
|
698
847
|
}
|
|
699
|
-
if (fixedErrors ===
|
|
700
|
-
|
|
848
|
+
if (fixedErrors === fileErrors && (!valModule.errors.fatal || valModule.errors.fatal.length == 0)) {
|
|
849
|
+
yield {
|
|
850
|
+
type: "file-valid",
|
|
851
|
+
file: moduleFilePath,
|
|
852
|
+
durationMs: Date.now() - start
|
|
853
|
+
};
|
|
701
854
|
}
|
|
702
855
|
for (const fatalError of valModule.errors.fatal || []) {
|
|
703
|
-
|
|
704
|
-
|
|
856
|
+
fileErrors += 1;
|
|
857
|
+
yield {
|
|
858
|
+
type: "fatal-error",
|
|
859
|
+
file: moduleFilePath,
|
|
860
|
+
message: fatalError.message
|
|
861
|
+
};
|
|
705
862
|
}
|
|
706
863
|
} else {
|
|
707
|
-
|
|
864
|
+
yield {
|
|
865
|
+
type: "file-valid",
|
|
866
|
+
file: moduleFilePath,
|
|
867
|
+
durationMs: Date.now() - start
|
|
868
|
+
};
|
|
708
869
|
}
|
|
709
|
-
if (
|
|
710
|
-
|
|
870
|
+
if (fileErrors > 0) {
|
|
871
|
+
yield {
|
|
872
|
+
type: "file-error-count",
|
|
873
|
+
file: `/${file}`,
|
|
874
|
+
errorCount: fileErrors,
|
|
875
|
+
durationMs: Date.now() - start
|
|
876
|
+
};
|
|
711
877
|
}
|
|
712
|
-
|
|
878
|
+
errors += fileErrors;
|
|
713
879
|
}
|
|
714
880
|
}
|
|
715
881
|
for (const file of valFiles.sort()) {
|
|
716
|
-
|
|
717
|
-
errors += await validateFile(file);
|
|
718
|
-
if (prettier && didFix) {
|
|
719
|
-
var _prettier;
|
|
720
|
-
const filePath = path__default["default"].join(projectRoot, file);
|
|
721
|
-
const fileContent = await fs__default["default"].readFile(filePath, "utf-8");
|
|
722
|
-
const formattedContent = await ((_prettier = prettier) === null || _prettier === void 0 ? void 0 : _prettier.format(fileContent, {
|
|
723
|
-
filepath: filePath
|
|
724
|
-
}));
|
|
725
|
-
await fs__default["default"].writeFile(filePath, formattedContent);
|
|
726
|
-
}
|
|
882
|
+
yield* validateFile(file);
|
|
727
883
|
}
|
|
884
|
+
service.dispose();
|
|
728
885
|
if (errors > 0) {
|
|
729
|
-
|
|
730
|
-
|
|
886
|
+
yield {
|
|
887
|
+
type: "summary-errors",
|
|
888
|
+
count: errors
|
|
889
|
+
};
|
|
731
890
|
} else {
|
|
732
|
-
|
|
891
|
+
yield {
|
|
892
|
+
type: "summary-success"
|
|
893
|
+
};
|
|
733
894
|
}
|
|
734
|
-
service.dispose();
|
|
735
|
-
return;
|
|
736
895
|
}
|
|
737
896
|
|
|
738
897
|
// GPT generated levenshtein distance algorithm:
|
|
@@ -760,6 +919,102 @@ function findSimilar(key, targets) {
|
|
|
760
919
|
})).sort((a, b) => a.distance - b.distance);
|
|
761
920
|
}
|
|
762
921
|
|
|
922
|
+
async function validate({
|
|
923
|
+
root,
|
|
924
|
+
fix
|
|
925
|
+
}) {
|
|
926
|
+
const projectRoot = root ? path__default["default"].resolve(root) : process.cwd();
|
|
927
|
+
const valConfigFile = (await evalValConfigFile(projectRoot, "val.config.ts")) || (await evalValConfigFile(projectRoot, "val.config.js"));
|
|
928
|
+
const resolvedValConfigFile = valConfigFile ? {
|
|
929
|
+
...valConfigFile,
|
|
930
|
+
project: process.env.VAL_PROJECT || valConfigFile.project
|
|
931
|
+
} : process.env.VAL_PROJECT ? {
|
|
932
|
+
project: process.env.VAL_PROJECT
|
|
933
|
+
} : undefined;
|
|
934
|
+
console.log(pc__default["default"].greenBright(`Validating project${resolvedValConfigFile !== null && resolvedValConfigFile !== void 0 && resolvedValConfigFile.project ? ` '${pc__default["default"].inverse(resolvedValConfigFile.project)}'` : ""}...`));
|
|
935
|
+
const valFiles = await fastGlob.glob("**/*.val.{js,ts}", {
|
|
936
|
+
ignore: ["node_modules/**"],
|
|
937
|
+
cwd: projectRoot
|
|
938
|
+
});
|
|
939
|
+
console.log(pc__default["default"].greenBright(`Found ${valFiles.length} files...`));
|
|
940
|
+
let prettier;
|
|
941
|
+
try {
|
|
942
|
+
prettier = (await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('prettier')); })).default;
|
|
943
|
+
} catch {
|
|
944
|
+
console.log("Prettier not found, skipping formatting");
|
|
945
|
+
}
|
|
946
|
+
const fixedFiles = new Set();
|
|
947
|
+
let totalErrors = 0;
|
|
948
|
+
for await (const event of runValidation({
|
|
949
|
+
root: projectRoot,
|
|
950
|
+
fix: !!fix,
|
|
951
|
+
valFiles,
|
|
952
|
+
project: resolvedValConfigFile === null || resolvedValConfigFile === void 0 ? void 0 : resolvedValConfigFile.project,
|
|
953
|
+
remote: {
|
|
954
|
+
remoteHost: process.env.VAL_REMOTE_HOST || core.DEFAULT_VAL_REMOTE_HOST,
|
|
955
|
+
getSettings: (projectName, options) => server.getSettings(projectName, options),
|
|
956
|
+
uploadFile: (project, bucket, fileHash, fileExt, fileBuffer, options) => server.uploadRemoteFile(process.env.VAL_CONTENT_URL || core.DEFAULT_CONTENT_HOST, project, bucket, fileHash, fileExt ?? "", fileBuffer, options)
|
|
957
|
+
},
|
|
958
|
+
fs: createDefaultValFSHost()
|
|
959
|
+
})) {
|
|
960
|
+
switch (event.type) {
|
|
961
|
+
case "file-valid":
|
|
962
|
+
console.log(pc__default["default"].green("✔"), event.file, "is valid (" + event.durationMs + "ms)");
|
|
963
|
+
break;
|
|
964
|
+
case "file-error-count":
|
|
965
|
+
console.log(pc__default["default"].red("✘"), `${event.file} contains ${event.errorCount} error${event.errorCount > 1 ? "s" : ""}`, " (" + event.durationMs + "ms)");
|
|
966
|
+
totalErrors += event.errorCount;
|
|
967
|
+
break;
|
|
968
|
+
case "validation-error":
|
|
969
|
+
console.log(pc__default["default"].red("✘"), "Got error in", `${event.sourcePath}:`, event.message);
|
|
970
|
+
break;
|
|
971
|
+
case "validation-fixable-error":
|
|
972
|
+
console.log(event.fixable ? pc__default["default"].yellow("⚠") : pc__default["default"].red("✘"), `Got ${event.fixable ? "fixable " : ""}error in`, `${event.sourcePath}:`, event.message);
|
|
973
|
+
break;
|
|
974
|
+
case "unknown-fix":
|
|
975
|
+
console.log(pc__default["default"].red("✘"), "Unknown fix", event.fixes, "for", event.sourcePath);
|
|
976
|
+
break;
|
|
977
|
+
case "fix-applied":
|
|
978
|
+
console.log(pc__default["default"].yellow("⚠"), "Applied fix for", event.sourcePath);
|
|
979
|
+
fixedFiles.add(event.file);
|
|
980
|
+
break;
|
|
981
|
+
case "fatal-error":
|
|
982
|
+
console.log(pc__default["default"].red("✘"), event.file, "is invalid:", event.message);
|
|
983
|
+
break;
|
|
984
|
+
case "remote-uploading":
|
|
985
|
+
console.log(pc__default["default"].yellow("⚠"), `Uploading remote file: '${event.ref}'...`);
|
|
986
|
+
break;
|
|
987
|
+
case "remote-uploaded":
|
|
988
|
+
console.log(pc__default["default"].green("✔"), `Completed upload of remote file: '${event.ref}'`);
|
|
989
|
+
break;
|
|
990
|
+
case "remote-already-uploaded":
|
|
991
|
+
console.log(pc__default["default"].yellow("⚠"), `Remote file ${event.filePath} already uploaded`);
|
|
992
|
+
break;
|
|
993
|
+
case "remote-downloading":
|
|
994
|
+
console.log(pc__default["default"].yellow("⚠"), `Downloading remote file in ${event.sourcePath}...`);
|
|
995
|
+
break;
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
// Run prettier on files that had fixes applied
|
|
1000
|
+
if (prettier) {
|
|
1001
|
+
for (const file of fixedFiles) {
|
|
1002
|
+
const filePath = path__default["default"].join(projectRoot, file);
|
|
1003
|
+
const fileContent = await fs__default["default"].readFile(filePath, "utf-8");
|
|
1004
|
+
const formattedContent = await prettier.format(fileContent, {
|
|
1005
|
+
filepath: filePath
|
|
1006
|
+
});
|
|
1007
|
+
await fs__default["default"].writeFile(filePath, formattedContent);
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
if (totalErrors > 0) {
|
|
1011
|
+
console.log(pc__default["default"].red("✘"), "Got", totalErrors, "error" + (totalErrors > 1 ? "s" : ""));
|
|
1012
|
+
process.exit(1);
|
|
1013
|
+
} else {
|
|
1014
|
+
console.log(pc__default["default"].green("✔"), "No validation errors found");
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
|
|
763
1018
|
async function listUnusedFiles({
|
|
764
1019
|
root
|
|
765
1020
|
}) {
|
|
@@ -867,7 +1122,7 @@ async function connect(options) {
|
|
|
867
1122
|
params.set("github_repo", [maybeGitOwnerAndRepo.owner, maybeGitOwnerAndRepo.repo].join("/"));
|
|
868
1123
|
}
|
|
869
1124
|
const url = `${host$1}/connect?${params.toString()}`;
|
|
870
|
-
console.log(
|
|
1125
|
+
console.log(pc__default["default"].dim(`\nFollow the instructions in your browser to complete the setup:\n${pc__default["default"].cyan(url)}\n`));
|
|
871
1126
|
}
|
|
872
1127
|
async function tryGetProject(projectRoot) {
|
|
873
1128
|
const valConfigFile = (await evalValConfigFile(projectRoot, "val.config.ts")) || (await evalValConfigFile(projectRoot, "val.config.js"));
|
|
@@ -879,7 +1134,7 @@ async function tryGetProject(projectRoot) {
|
|
|
879
1134
|
projectName: parts[1]
|
|
880
1135
|
};
|
|
881
1136
|
} else {
|
|
882
|
-
console.error(
|
|
1137
|
+
console.error(pc__default["default"].red(`Invalid project format in val.config file: "${valConfigFile.project}". Expected format "orgName/projectName".`));
|
|
883
1138
|
process.exit(1);
|
|
884
1139
|
}
|
|
885
1140
|
}
|
|
@@ -914,7 +1169,7 @@ async function tryGetGitRemote(root) {
|
|
|
914
1169
|
}
|
|
915
1170
|
return null;
|
|
916
1171
|
} catch (error) {
|
|
917
|
-
console.error(
|
|
1172
|
+
console.error(pc__default["default"].red("Failed to read .git/config file."), error);
|
|
918
1173
|
return null;
|
|
919
1174
|
}
|
|
920
1175
|
}
|
|
@@ -923,8 +1178,8 @@ function tryGetGitConfig(root) {
|
|
|
923
1178
|
let lastDir = null;
|
|
924
1179
|
while (currentDir !== lastDir) {
|
|
925
1180
|
const gitConfigPath = path__default["default"].join(currentDir, ".git", "config");
|
|
926
|
-
if (
|
|
927
|
-
return
|
|
1181
|
+
if (nodeFs__default["default"].existsSync(gitConfigPath)) {
|
|
1182
|
+
return nodeFs__default["default"].readFileSync(gitConfigPath, "utf-8");
|
|
928
1183
|
}
|
|
929
1184
|
lastDir = currentDir;
|
|
930
1185
|
currentDir = path__default["default"].dirname(currentDir);
|
|
@@ -939,7 +1194,7 @@ const host = process.env.VAL_BUILD_URL || "https://admin.val.build";
|
|
|
939
1194
|
async function login(options) {
|
|
940
1195
|
try {
|
|
941
1196
|
var _response$headers$get;
|
|
942
|
-
console.log(
|
|
1197
|
+
console.log(pc__default["default"].cyan("\nStarting login process...\n"));
|
|
943
1198
|
|
|
944
1199
|
// Step 1: Initiate login and get token and URL
|
|
945
1200
|
const response = await fetch(`${host}/api/login`, {
|
|
@@ -952,7 +1207,7 @@ async function login(options) {
|
|
|
952
1207
|
let url;
|
|
953
1208
|
if (!((_response$headers$get = response.headers.get("content-type")) !== null && _response$headers$get !== void 0 && _response$headers$get.includes("application/json"))) {
|
|
954
1209
|
const text = await response.text();
|
|
955
|
-
console.error(
|
|
1210
|
+
console.error(pc__default["default"].red("Unexpected failure while trying to login (content type was not JSON). "), text ? `Server response: ${text} (status: ${response.status})` : `Status: ${response.status}`);
|
|
956
1211
|
process.exit(1);
|
|
957
1212
|
}
|
|
958
1213
|
const json = await response.json();
|
|
@@ -961,12 +1216,12 @@ async function login(options) {
|
|
|
961
1216
|
url = json.url;
|
|
962
1217
|
}
|
|
963
1218
|
if (!token || !url) {
|
|
964
|
-
console.error(
|
|
1219
|
+
console.error(pc__default["default"].red("Unexpected response from the server."), json);
|
|
965
1220
|
process.exit(1);
|
|
966
1221
|
}
|
|
967
|
-
console.log(
|
|
968
|
-
console.log(
|
|
969
|
-
console.log(
|
|
1222
|
+
console.log(pc__default["default"].green("Open the following URL in your browser to log in:"));
|
|
1223
|
+
console.log(pc__default["default"].underline(pc__default["default"].blue(url)));
|
|
1224
|
+
console.log(pc__default["default"].dim("\nWaiting for login confirmation...\n"));
|
|
970
1225
|
|
|
971
1226
|
// Step 2: Poll for login confirmation
|
|
972
1227
|
const result = await pollForConfirmation(token);
|
|
@@ -975,7 +1230,7 @@ async function login(options) {
|
|
|
975
1230
|
const filePath = server.getPersonalAccessTokenPath(options.root || process.cwd());
|
|
976
1231
|
saveToken(result, filePath);
|
|
977
1232
|
} catch (error) {
|
|
978
|
-
console.error(
|
|
1233
|
+
console.error(pc__default["default"].red("An error occurred during the login process. Check your internet connection. Details:"), error instanceof Error ? error.message : JSON.stringify(error, null, 2));
|
|
979
1234
|
process.exit(1);
|
|
980
1235
|
}
|
|
981
1236
|
}
|
|
@@ -988,7 +1243,7 @@ async function pollForConfirmation(token) {
|
|
|
988
1243
|
method: "POST"
|
|
989
1244
|
});
|
|
990
1245
|
if (response.status === 500) {
|
|
991
|
-
console.error(
|
|
1246
|
+
console.error(pc__default["default"].red("An error occurred on the server."));
|
|
992
1247
|
process.exit(1);
|
|
993
1248
|
}
|
|
994
1249
|
if (response.status === 200) {
|
|
@@ -997,21 +1252,21 @@ async function pollForConfirmation(token) {
|
|
|
997
1252
|
if (typeof json.profile.email === "string" && typeof json.pat === "string") {
|
|
998
1253
|
return json;
|
|
999
1254
|
} else {
|
|
1000
|
-
console.error(
|
|
1255
|
+
console.error(pc__default["default"].red("Unexpected response from the server."));
|
|
1001
1256
|
process.exit(1);
|
|
1002
1257
|
}
|
|
1003
1258
|
}
|
|
1004
1259
|
}
|
|
1005
1260
|
}
|
|
1006
|
-
console.error(
|
|
1261
|
+
console.error(pc__default["default"].red("Login confirmation timed out."));
|
|
1007
1262
|
process.exit(1);
|
|
1008
1263
|
}
|
|
1009
1264
|
function saveToken(result, filePath) {
|
|
1010
|
-
|
|
1265
|
+
nodeFs__default["default"].mkdirSync(path__default["default"].dirname(filePath), {
|
|
1011
1266
|
recursive: true
|
|
1012
1267
|
});
|
|
1013
|
-
|
|
1014
|
-
console.log(
|
|
1268
|
+
nodeFs__default["default"].writeFileSync(filePath, JSON.stringify(result, null, 2));
|
|
1269
|
+
console.log(pc__default["default"].green(`Token for ${pc__default["default"].cyan(result.profile.email)} saved to ${pc__default["default"].cyan(filePath)}`));
|
|
1015
1270
|
}
|
|
1016
1271
|
|
|
1017
1272
|
async function main() {
|