@valbuild/init 0.60.18 → 0.60.20
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/main/dist/valbuild-init-main.cjs.dev.js +214 -20
- package/main/dist/valbuild-init-main.cjs.prod.js +214 -20
- package/main/dist/valbuild-init-main.esm.js +214 -20
- package/package.json +1 -1
- package/src/init.ts +196 -6
- package/src/logger.ts +3 -3
- package/src/templates.ts +135 -0
|
@@ -406,6 +406,59 @@ function _slicedToArray(arr, i) {
|
|
|
406
406
|
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
|
|
407
407
|
}
|
|
408
408
|
|
|
409
|
+
function toPrimitive(t, r) {
|
|
410
|
+
if ("object" != typeof t || !t) return t;
|
|
411
|
+
var e = t[Symbol.toPrimitive];
|
|
412
|
+
if (void 0 !== e) {
|
|
413
|
+
var i = e.call(t, r || "default");
|
|
414
|
+
if ("object" != typeof i) return i;
|
|
415
|
+
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
416
|
+
}
|
|
417
|
+
return ("string" === r ? String : Number)(t);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
function toPropertyKey(t) {
|
|
421
|
+
var i = toPrimitive(t, "string");
|
|
422
|
+
return "symbol" == typeof i ? i : String(i);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
function _defineProperty(obj, key, value) {
|
|
426
|
+
key = toPropertyKey(key);
|
|
427
|
+
if (key in obj) {
|
|
428
|
+
Object.defineProperty(obj, key, {
|
|
429
|
+
value: value,
|
|
430
|
+
enumerable: true,
|
|
431
|
+
configurable: true,
|
|
432
|
+
writable: true
|
|
433
|
+
});
|
|
434
|
+
} else {
|
|
435
|
+
obj[key] = value;
|
|
436
|
+
}
|
|
437
|
+
return obj;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
function ownKeys(e, r) {
|
|
441
|
+
var t = Object.keys(e);
|
|
442
|
+
if (Object.getOwnPropertySymbols) {
|
|
443
|
+
var o = Object.getOwnPropertySymbols(e);
|
|
444
|
+
r && (o = o.filter(function (r) {
|
|
445
|
+
return Object.getOwnPropertyDescriptor(e, r).enumerable;
|
|
446
|
+
})), t.push.apply(t, o);
|
|
447
|
+
}
|
|
448
|
+
return t;
|
|
449
|
+
}
|
|
450
|
+
function _objectSpread2(e) {
|
|
451
|
+
for (var r = 1; r < arguments.length; r++) {
|
|
452
|
+
var t = null != arguments[r] ? arguments[r] : {};
|
|
453
|
+
r % 2 ? ownKeys(Object(t), !0).forEach(function (r) {
|
|
454
|
+
_defineProperty(e, r, t[r]);
|
|
455
|
+
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) {
|
|
456
|
+
Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
return e;
|
|
460
|
+
}
|
|
461
|
+
|
|
409
462
|
function transformNextAppRouterValProvider(fileInfo, api, options) {
|
|
410
463
|
if (!options.configImportPath) {
|
|
411
464
|
throw new Error("configImportPath is required");
|
|
@@ -451,7 +504,7 @@ function transformNextAppRouterValProvider(fileInfo, api, options) {
|
|
|
451
504
|
|
|
452
505
|
var packageJson = {
|
|
453
506
|
name: "@valbuild/init",
|
|
454
|
-
version: "0.60.
|
|
507
|
+
version: "0.60.20",
|
|
455
508
|
description: "Initialize a new val.build project",
|
|
456
509
|
exports: {
|
|
457
510
|
"./main": {
|
|
@@ -522,12 +575,15 @@ var VAL_API_ROUTER = function VAL_API_ROUTER(valServerPath) {
|
|
|
522
575
|
var VAL_APP_PAGE = function VAL_APP_PAGE(configImportPath) {
|
|
523
576
|
return "import { ValApp } from \"@valbuild/next\";\nimport { config } from \"".concat(configImportPath, "\";\n\nexport default function Val() {\n return <ValApp config={config} />;\n}\n");
|
|
524
577
|
};
|
|
578
|
+
var BASIC_EXAMPLE = function BASIC_EXAMPLE(moduleId, configImportPath, isJavaScript) {
|
|
579
|
+
return "".concat(isJavaScript ? "// @ts-check\n" : "", "/**\n * Val example file - generated by @valbuild/init\n **/\n\nimport {\n s /* s = schema */,\n c /* c = content */,").concat(isJavaScript ? "" : "\n type t /* t = type */,", "\n} from \"").concat(configImportPath, "\";\n\n/**\n * This is the schema for the content. It defines the structure of the content and the types of each field.\n *\n * @docs https://val.build/docs/api-reference\n */\nexport const testSchema = s.object({\n /**\n * Basic text field\n */\n text: s.string(),\n\n /**\n * Optional fields are marked with `.optional()`\n */\n optionals: s.string().optional(),\n\n arrays: s.array(s.string()),\n /**\n * Records are objects where entries can be added. Useful for array-like structures where you would use a key to uniquely identify each entry.\n */\n records: s.record(s.string()),\n\n /**\n * Rich text can be used for multiline text, but also for more complex text editing capabilities like links, images, lists, etc.\n *\n * @docs https://val.build/docs/api-reference/schema-types/richtext\n *\n * @see ValRichText will render rich text\n */\n richText: s.richtext({\n // All features enabled:\n bold: true,\n italic: true,\n lineThrough: true,\n headings: [\"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\"],\n a: true,\n img: true,\n ul: true,\n ol: true,\n }),\n\n /**\n * Images in Val are stored as files in the public folder.\n *\n * @docs https://val.build/docs/api-reference/schema-types/image\n *\n * When defining content use the following syntax:\n * @example c.file('/public/myimage.png') // path to the image file, use the VS Code plugin or the `@valbuild/cli validate --fix` command to add metadata\n *\n * @see ValImage component to see how to render this in your app\n */\n image: s.image().optional(),\n\n /**\n * String enums: presents as a dropdown in the UI\n */\n stringEnum: s.union(s.literal(\"lit-0\"), s.literal(\"lit-1\")),\n\n /**\n * Raw strings disables the stega (steganography) feature that automatically tags content when using the overlay.\n * It is useful for slugs and other data that might be processed in code (parsed or matching for equality...)\n */\n slug: s.string().raw(),\n\n /**\n * Object unions: presents as a dropdown in the UI and the different fields\n *\n * @docs https://val.build/docs/api-reference/schema-types/union\n */\n objectUnions: s.union(\n \"type\",\n s.object({\n type: s.literal(\"page-type-1\"),\n value: s.number(),\n }),\n s.object({\n type: s.literal(\"page-type-2\"),\n text: s.string(),\n })\n ),\n});\n").concat(isJavaScript ? "" : "\n/**\n * t.inferSchema returns the type of the content.\n * This pattern is useful to type props of components that use this content (partially or whole)\n */\nexport type TestContent = t.inferSchema<typeof testSchema>;\n", "\n\n/**\n * This is the content definition. Add your content below.\n *\n * NOTE: the first argument, module id, must match the path of the file.\n */\nexport default c.define(\"").concat(moduleId, "\", testSchema, {\n text: \"Basic text content\",\n optionals: null,\n arrays: [\"A string\"],\n records: {\n \"unique-key-1\": \"A string\",\n },\n richText: c.richtext`# Title 1\n\n${c.rt.link(\"Val docs\", { href: \"https://val.build/docs\" })}\n\n- List item 1\n- List item 2\n`,\n image: null,\n slug: \"test\",\n objectUnions: {\n type: \"page-type-2\",\n text: \"String value\",\n },\n stringEnum: \"lit-1\",\n});\n");
|
|
580
|
+
};
|
|
525
581
|
|
|
526
582
|
function error(message) {
|
|
527
|
-
console.error(chalk.red("❌ ERROR: ") + message);
|
|
583
|
+
console.error(chalk.red(" ❌ ERROR: ") + message);
|
|
528
584
|
}
|
|
529
585
|
function warn(message) {
|
|
530
|
-
console.error(chalk.yellow("⚠️ WARN:"
|
|
586
|
+
console.error(chalk.yellow(" ⚠️ WARN:" + message));
|
|
531
587
|
}
|
|
532
588
|
function info(message) {
|
|
533
589
|
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
@@ -536,7 +592,7 @@ function info(message) {
|
|
|
536
592
|
return;
|
|
537
593
|
}
|
|
538
594
|
if (opts.isGood) {
|
|
539
|
-
console.log(chalk.
|
|
595
|
+
console.log(chalk.hex("#37cd99")(" V") + message);
|
|
540
596
|
return;
|
|
541
597
|
}
|
|
542
598
|
console.log(message);
|
|
@@ -561,7 +617,7 @@ function _init() {
|
|
|
561
617
|
case 0:
|
|
562
618
|
root = _args2.length > 0 && _args2[0] !== undefined ? _args2[0] : process.cwd();
|
|
563
619
|
_ref = _args2.length > 1 && _args2[1] !== undefined ? _args2[1] : {}, defaultAnswers = _ref.yes;
|
|
564
|
-
info(
|
|
620
|
+
info("Initializing " + chalk.bgBlack.hex("#37cd99")("Val") + ' in "' + root + '"...\n');
|
|
565
621
|
process.stdout.write("Analyzing project...");
|
|
566
622
|
_context2.next = 6;
|
|
567
623
|
return analyze(path.resolve(root), walk(path.resolve(root)));
|
|
@@ -608,7 +664,7 @@ function walk(dir) {
|
|
|
608
664
|
}
|
|
609
665
|
var analyze = /*#__PURE__*/function () {
|
|
610
666
|
var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(root, files) {
|
|
611
|
-
var analysis, packageJsonPath, packageJsonText, _packageJson, _semver$minVersion, minNextVersion, _semver$minVersion2, minValVersion, pagesRouterAppPath, appRouterLayoutPath, git, gitStatus, gitRemoteOrigin;
|
|
667
|
+
var analysis, packageJsonPath, packageJsonText, _packageJson, _semver$minVersion, minNextVersion, _semver$minVersion2, minValVersion, pagesRouterAppPath, appRouterLayoutPath, git, gitStatus, gitRemoteOrigin, parts, owner, repo, gitIgnorePath;
|
|
612
668
|
return _regeneratorRuntime().wrap(function _callee$(_context) {
|
|
613
669
|
while (1) switch (_context.prev = _context.next) {
|
|
614
670
|
case 0:
|
|
@@ -720,18 +776,32 @@ var analyze = /*#__PURE__*/function () {
|
|
|
720
776
|
analysis.hasGit = true;
|
|
721
777
|
analysis.isGitHub = gitRemoteOrigin ? !!gitRemoteOrigin.includes("github.com") : false;
|
|
722
778
|
analysis.isGitClean = getGitStatusIsClean(gitStatus);
|
|
723
|
-
|
|
779
|
+
// get owner and repo from git remote:
|
|
780
|
+
if (gitRemoteOrigin) {
|
|
781
|
+
// Split the URL by colon
|
|
782
|
+
parts = gitRemoteOrigin.split(":"); // Extract owner and repo
|
|
783
|
+
owner = parts[0].split("@")[1];
|
|
784
|
+
repo = parts[1].replace(".git", ""); // Remove .git extension if present
|
|
785
|
+
analysis.gitRemote = {
|
|
786
|
+
owner: owner,
|
|
787
|
+
repo: repo
|
|
788
|
+
};
|
|
789
|
+
}
|
|
790
|
+
_context.next = 47;
|
|
724
791
|
break;
|
|
725
|
-
case
|
|
726
|
-
_context.prev =
|
|
792
|
+
case 45:
|
|
793
|
+
_context.prev = 45;
|
|
727
794
|
_context.t1 = _context["catch"](31);
|
|
728
|
-
case 46:
|
|
729
|
-
return _context.abrupt("return", analysis);
|
|
730
795
|
case 47:
|
|
796
|
+
gitIgnorePath = path.join(root, ".gitignore");
|
|
797
|
+
analysis.gitIgnorePath = gitIgnorePath;
|
|
798
|
+
analysis.gitIgnoreFile = fs.readFileSync(gitIgnorePath, "utf-8");
|
|
799
|
+
return _context.abrupt("return", analysis);
|
|
800
|
+
case 51:
|
|
731
801
|
case "end":
|
|
732
802
|
return _context.stop();
|
|
733
803
|
}
|
|
734
|
-
}, _callee, null, [[8, 17], [31,
|
|
804
|
+
}, _callee, null, [[8, 17], [31, 45]]);
|
|
735
805
|
}));
|
|
736
806
|
return function analyze(_x, _x2) {
|
|
737
807
|
return _ref2.apply(this, arguments);
|
|
@@ -768,6 +838,19 @@ function _plan() {
|
|
|
768
838
|
_answer7,
|
|
769
839
|
currentEslintRc,
|
|
770
840
|
parsedEslint,
|
|
841
|
+
_answer8,
|
|
842
|
+
_answer9,
|
|
843
|
+
vscodeDir,
|
|
844
|
+
settingsPath,
|
|
845
|
+
currentSettings,
|
|
846
|
+
currentSettingsFile,
|
|
847
|
+
currentRecommendations,
|
|
848
|
+
valBuildIntelliSense,
|
|
849
|
+
_answer10,
|
|
850
|
+
exampleDir,
|
|
851
|
+
examplePath,
|
|
852
|
+
exampleImport,
|
|
853
|
+
exampleModuleId,
|
|
771
854
|
_args3 = arguments;
|
|
772
855
|
return _regeneratorRuntime().wrap(function _callee3$(_context3) {
|
|
773
856
|
while (1) switch (_context3.prev = _context3.next) {
|
|
@@ -804,7 +887,7 @@ function _plan() {
|
|
|
804
887
|
_context3.next = 15;
|
|
805
888
|
break;
|
|
806
889
|
}
|
|
807
|
-
info(" Source dir: " + analysis.
|
|
890
|
+
info(" Source dir: " + analysis.srcDir, {
|
|
808
891
|
isGood: true
|
|
809
892
|
});
|
|
810
893
|
_context3.next = 17;
|
|
@@ -1304,12 +1387,117 @@ function _plan() {
|
|
|
1304
1387
|
case 202:
|
|
1305
1388
|
warn("Cannot patch eslint: failed to find eslint config file");
|
|
1306
1389
|
case 203:
|
|
1390
|
+
if (!analysis.gitIgnorePath) {
|
|
1391
|
+
_context3.next = 210;
|
|
1392
|
+
break;
|
|
1393
|
+
}
|
|
1394
|
+
_context3.next = 206;
|
|
1395
|
+
return confirm({
|
|
1396
|
+
message: "Append .gitignore entry for Val cache? (recommended)",
|
|
1397
|
+
"default": true
|
|
1398
|
+
});
|
|
1399
|
+
case 206:
|
|
1400
|
+
_answer8 = _context3.sent;
|
|
1401
|
+
if (_answer8) {
|
|
1402
|
+
plan.updateGitIgnore = {
|
|
1403
|
+
path: analysis.gitIgnorePath,
|
|
1404
|
+
source: (analysis.gitIgnoreFile ? "".concat(analysis.gitIgnoreFile, "\n\n") : "") + "# Val local cache\n.val\n"
|
|
1405
|
+
};
|
|
1406
|
+
} else {
|
|
1407
|
+
plan.updateGitIgnore = false;
|
|
1408
|
+
}
|
|
1409
|
+
_context3.next = 211;
|
|
1410
|
+
break;
|
|
1411
|
+
case 210:
|
|
1412
|
+
plan.updateGitIgnore = false;
|
|
1413
|
+
case 211:
|
|
1414
|
+
_context3.next = 213;
|
|
1415
|
+
return confirm({
|
|
1416
|
+
message: "Add the Val Build IntelliSense to .vscode/extensions.json?",
|
|
1417
|
+
"default": true
|
|
1418
|
+
});
|
|
1419
|
+
case 213:
|
|
1420
|
+
_answer9 = _context3.sent;
|
|
1421
|
+
if (!_answer9) {
|
|
1422
|
+
_context3.next = 239;
|
|
1423
|
+
break;
|
|
1424
|
+
}
|
|
1425
|
+
vscodeDir = path.join(analysis.root, ".vscode");
|
|
1426
|
+
settingsPath = path.join(vscodeDir, "extensions.json");
|
|
1427
|
+
currentSettings = {};
|
|
1428
|
+
_context3.prev = 218;
|
|
1429
|
+
currentSettingsFile = fs.readFileSync(settingsPath, "utf-8");
|
|
1430
|
+
if (!currentSettingsFile) {
|
|
1431
|
+
_context3.next = 229;
|
|
1432
|
+
break;
|
|
1433
|
+
}
|
|
1434
|
+
_context3.prev = 221;
|
|
1435
|
+
currentSettings = JSON.parse(currentSettingsFile);
|
|
1436
|
+
_context3.next = 229;
|
|
1437
|
+
break;
|
|
1438
|
+
case 225:
|
|
1439
|
+
_context3.prev = 225;
|
|
1440
|
+
_context3.t8 = _context3["catch"](221);
|
|
1441
|
+
warn("Failed to parse VS Code extensions.json found here: ".concat(settingsPath, ".").concat(_context3.t8 instanceof Error ? "Parse error: ".concat(_context3.t8.message) : ""));
|
|
1442
|
+
return _context3.abrupt("return", {
|
|
1443
|
+
abort: true
|
|
1444
|
+
});
|
|
1445
|
+
case 229:
|
|
1446
|
+
_context3.next = 233;
|
|
1447
|
+
break;
|
|
1448
|
+
case 231:
|
|
1449
|
+
_context3.prev = 231;
|
|
1450
|
+
_context3.t9 = _context3["catch"](218);
|
|
1451
|
+
case 233:
|
|
1452
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1453
|
+
currentRecommendations = currentSettings.recommendations;
|
|
1454
|
+
valBuildIntelliSense = "valbuild.vscode-val-build";
|
|
1455
|
+
if (!currentRecommendations.includes(valBuildIntelliSense)) {
|
|
1456
|
+
currentSettings = _objectSpread2(_objectSpread2({}, currentSettings), {}, {
|
|
1457
|
+
recommendations: (currentRecommendations || []).concat(valBuildIntelliSense)
|
|
1458
|
+
});
|
|
1459
|
+
}
|
|
1460
|
+
plan.updateVSCodeSettings = {
|
|
1461
|
+
path: settingsPath,
|
|
1462
|
+
source: JSON.stringify(currentSettings, null, 2)
|
|
1463
|
+
};
|
|
1464
|
+
_context3.next = 240;
|
|
1465
|
+
break;
|
|
1466
|
+
case 239:
|
|
1467
|
+
plan.updateVSCodeSettings = false;
|
|
1468
|
+
case 240:
|
|
1469
|
+
_context3.next = 242;
|
|
1470
|
+
return confirm({
|
|
1471
|
+
message: "Include example Val files?",
|
|
1472
|
+
"default": true
|
|
1473
|
+
});
|
|
1474
|
+
case 242:
|
|
1475
|
+
_answer10 = _context3.sent;
|
|
1476
|
+
if (!_answer10) {
|
|
1477
|
+
_context3.next = 251;
|
|
1478
|
+
break;
|
|
1479
|
+
}
|
|
1480
|
+
exampleDir = path.join(analysis.srcDir, "examples", "val");
|
|
1481
|
+
examplePath = path.join(exampleDir, "example.val." + (analysis.isJavaScript ? "js" : "ts"));
|
|
1482
|
+
exampleImport = path.relative(exampleDir, valConfigPath).replace(".js", "").replace(".ts", "");
|
|
1483
|
+
if (analysis.packageJsonDir) {
|
|
1484
|
+
_context3.next = 249;
|
|
1485
|
+
break;
|
|
1486
|
+
}
|
|
1487
|
+
throw Error("Could not detect package.json directory! This is a Val bug.");
|
|
1488
|
+
case 249:
|
|
1489
|
+
exampleModuleId = "/".concat(path.relative(analysis.packageJsonDir, examplePath).replace(".val", "").replace(".js", "").replace(".ts", ""));
|
|
1490
|
+
plan.includeExample = {
|
|
1491
|
+
path: examplePath,
|
|
1492
|
+
source: BASIC_EXAMPLE(exampleModuleId, exampleImport, !!analysis.isJavaScript)
|
|
1493
|
+
};
|
|
1494
|
+
case 251:
|
|
1307
1495
|
return _context3.abrupt("return", plan);
|
|
1308
|
-
case
|
|
1496
|
+
case 252:
|
|
1309
1497
|
case "end":
|
|
1310
1498
|
return _context3.stop();
|
|
1311
1499
|
}
|
|
1312
|
-
}, _callee3);
|
|
1500
|
+
}, _callee3, null, [[218, 231], [221, 225]]);
|
|
1313
1501
|
}));
|
|
1314
1502
|
return _plan.apply(this, arguments);
|
|
1315
1503
|
}
|
|
@@ -1318,7 +1506,7 @@ function execute(_x4) {
|
|
|
1318
1506
|
}
|
|
1319
1507
|
function _execute() {
|
|
1320
1508
|
_execute = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(plan) {
|
|
1321
|
-
var _i, _Object$entries, _Object$entries$_i, key,
|
|
1509
|
+
var _i, _Object$entries, _Object$entries$_i, key, maybeFileOp;
|
|
1322
1510
|
return _regeneratorRuntime().wrap(function _callee4$(_context4) {
|
|
1323
1511
|
while (1) switch (_context4.prev = _context4.next) {
|
|
1324
1512
|
case 0:
|
|
@@ -1336,10 +1524,13 @@ function _execute() {
|
|
|
1336
1524
|
case 4:
|
|
1337
1525
|
info("Executing...");
|
|
1338
1526
|
for (_i = 0, _Object$entries = Object.entries(plan); _i < _Object$entries.length; _i++) {
|
|
1339
|
-
_Object$entries$_i = _slicedToArray(_Object$entries[_i], 2), key = _Object$entries$_i[0],
|
|
1340
|
-
|
|
1527
|
+
_Object$entries$_i = _slicedToArray(_Object$entries[_i], 2), key = _Object$entries$_i[0], maybeFileOp = _Object$entries$_i[1];
|
|
1528
|
+
if (isFileOp(maybeFileOp)) {
|
|
1529
|
+
writeFile(maybeFileOp, plan.root, key.startsWith("update"));
|
|
1530
|
+
}
|
|
1341
1531
|
}
|
|
1342
|
-
|
|
1532
|
+
info("\n \nVal was successfully initialized!\n\n Start the application:\n\n $ ".concat(chalk.gray("npm run dev"), "\n\n Open (assumes http://localhost:3000):\n\n ").concat(chalk.bgBlack.hex("#37cd99").underline("http://localhost:3000/val"), "\n\n When you want to enable editor support, import the project by opening the following link:\n \n ").concat(chalk.bgBlack.hex("#37cd99").underline("https://app.val.build/orgs/new".concat(plan.gitRemote ? "?org=".concat(encodeURIComponent(plan.gitRemote.owner), "&owner=").concat(encodeURIComponent(plan.gitRemote.owner), "&repo=").concat(encodeURIComponent(plan.gitRemote.repo)) : "")), "\n\n"));
|
|
1533
|
+
case 7:
|
|
1343
1534
|
case "end":
|
|
1344
1535
|
return _context4.stop();
|
|
1345
1536
|
}
|
|
@@ -1348,7 +1539,7 @@ function _execute() {
|
|
|
1348
1539
|
return _execute.apply(this, arguments);
|
|
1349
1540
|
}
|
|
1350
1541
|
function writeFile(fileOp, rootDir, isUpdate) {
|
|
1351
|
-
if (fileOp
|
|
1542
|
+
if (fileOp) {
|
|
1352
1543
|
fs.mkdirSync(path.dirname(fileOp.path), {
|
|
1353
1544
|
recursive: true
|
|
1354
1545
|
});
|
|
@@ -1378,6 +1569,9 @@ function getGitStatusIsClean(gitStatus) {
|
|
|
1378
1569
|
}
|
|
1379
1570
|
return false;
|
|
1380
1571
|
}
|
|
1572
|
+
function isFileOp(maybeFileOp) {
|
|
1573
|
+
return typeof maybeFileOp !== "boolean" && typeof maybeFileOp !== "string" && _typeof(maybeFileOp) === "object" && !!maybeFileOp && "path" in maybeFileOp && "source" in maybeFileOp && typeof maybeFileOp.path === "string" && typeof maybeFileOp.source === "string";
|
|
1574
|
+
}
|
|
1381
1575
|
|
|
1382
1576
|
function main() {
|
|
1383
1577
|
return _main.apply(this, arguments);
|
package/package.json
CHANGED
package/src/init.ts
CHANGED
|
@@ -9,6 +9,7 @@ import jcs from "jscodeshift";
|
|
|
9
9
|
import semver from "semver";
|
|
10
10
|
import packageJson from "../package.json";
|
|
11
11
|
import {
|
|
12
|
+
BASIC_EXAMPLE,
|
|
12
13
|
VAL_API_ROUTER,
|
|
13
14
|
VAL_APP_PAGE,
|
|
14
15
|
VAL_CLIENT,
|
|
@@ -26,7 +27,13 @@ export async function init(
|
|
|
26
27
|
root: string = process.cwd(),
|
|
27
28
|
{ yes: defaultAnswers }: { yes?: boolean } = {}
|
|
28
29
|
) {
|
|
29
|
-
logger.info(
|
|
30
|
+
logger.info(
|
|
31
|
+
"Initializing " +
|
|
32
|
+
chalk.bgBlack.hex("#37cd99")("Val") +
|
|
33
|
+
' in "' +
|
|
34
|
+
root +
|
|
35
|
+
'"...\n'
|
|
36
|
+
);
|
|
30
37
|
process.stdout.write("Analyzing project...");
|
|
31
38
|
const analysis = await analyze(path.resolve(root), walk(path.resolve(root)));
|
|
32
39
|
// reset cursor:
|
|
@@ -96,6 +103,12 @@ type Analysis = Partial<{
|
|
|
96
103
|
hasGit: boolean;
|
|
97
104
|
isGitHub: boolean;
|
|
98
105
|
isGitClean: boolean | "packages";
|
|
106
|
+
gitIgnorePath: string;
|
|
107
|
+
gitIgnoreFile?: string;
|
|
108
|
+
gitRemote: {
|
|
109
|
+
owner: string;
|
|
110
|
+
repo: string;
|
|
111
|
+
};
|
|
99
112
|
|
|
100
113
|
// TODO:
|
|
101
114
|
// check if modules are used
|
|
@@ -208,9 +221,26 @@ const analyze = async (root: string, files: string[]): Promise<Analysis> => {
|
|
|
208
221
|
? !!gitRemoteOrigin.includes("github.com")
|
|
209
222
|
: false;
|
|
210
223
|
analysis.isGitClean = getGitStatusIsClean(gitStatus);
|
|
224
|
+
// get owner and repo from git remote:
|
|
225
|
+
if (gitRemoteOrigin) {
|
|
226
|
+
// Split the URL by colon
|
|
227
|
+
const parts = gitRemoteOrigin.split(":");
|
|
228
|
+
|
|
229
|
+
// Extract owner and repo
|
|
230
|
+
const owner = parts[0].split("@")[1];
|
|
231
|
+
const repo = parts[1].replace(".git", ""); // Remove .git extension if present
|
|
232
|
+
|
|
233
|
+
analysis.gitRemote = {
|
|
234
|
+
owner,
|
|
235
|
+
repo,
|
|
236
|
+
};
|
|
237
|
+
}
|
|
211
238
|
} catch (err) {
|
|
212
239
|
// console.error(err);
|
|
213
240
|
}
|
|
241
|
+
const gitIgnorePath = path.join(root, ".gitignore");
|
|
242
|
+
analysis.gitIgnorePath = gitIgnorePath;
|
|
243
|
+
analysis.gitIgnoreFile = fs.readFileSync(gitIgnorePath, "utf-8");
|
|
214
244
|
return analysis;
|
|
215
245
|
};
|
|
216
246
|
|
|
@@ -232,6 +262,15 @@ type Plan = Partial<{
|
|
|
232
262
|
useJavascript: boolean;
|
|
233
263
|
abort: boolean;
|
|
234
264
|
ignoreGitDirty: boolean;
|
|
265
|
+
updateGitIgnore: false | FileOp;
|
|
266
|
+
gitRemote:
|
|
267
|
+
| false
|
|
268
|
+
| {
|
|
269
|
+
owner: string;
|
|
270
|
+
repo: string;
|
|
271
|
+
};
|
|
272
|
+
includeExample: false | FileOp;
|
|
273
|
+
updateVSCodeSettings: false | FileOp;
|
|
235
274
|
}>;
|
|
236
275
|
|
|
237
276
|
async function plan(
|
|
@@ -255,7 +294,7 @@ async function plan(
|
|
|
255
294
|
return { abort: true };
|
|
256
295
|
}
|
|
257
296
|
if (analysis.srcDir) {
|
|
258
|
-
logger.info(" Source dir: " + analysis.
|
|
297
|
+
logger.info(" Source dir: " + analysis.srcDir, { isGood: true });
|
|
259
298
|
} else {
|
|
260
299
|
logger.error("Failed to determine source directory");
|
|
261
300
|
return { abort: true };
|
|
@@ -610,6 +649,113 @@ async function plan(
|
|
|
610
649
|
}
|
|
611
650
|
}
|
|
612
651
|
|
|
652
|
+
{
|
|
653
|
+
if (analysis.gitIgnorePath) {
|
|
654
|
+
const answer = await confirm({
|
|
655
|
+
message: "Append .gitignore entry for Val cache? (recommended)",
|
|
656
|
+
default: true,
|
|
657
|
+
});
|
|
658
|
+
if (answer) {
|
|
659
|
+
plan.updateGitIgnore = {
|
|
660
|
+
path: analysis.gitIgnorePath,
|
|
661
|
+
source:
|
|
662
|
+
(analysis.gitIgnoreFile ? `${analysis.gitIgnoreFile}\n\n` : "") +
|
|
663
|
+
"# Val local cache\n.val\n",
|
|
664
|
+
};
|
|
665
|
+
} else {
|
|
666
|
+
plan.updateGitIgnore = false;
|
|
667
|
+
}
|
|
668
|
+
} else {
|
|
669
|
+
plan.updateGitIgnore = false;
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
{
|
|
673
|
+
const answer = await confirm({
|
|
674
|
+
message: "Add the Val Build IntelliSense to .vscode/extensions.json?",
|
|
675
|
+
default: true,
|
|
676
|
+
});
|
|
677
|
+
if (answer) {
|
|
678
|
+
const vscodeDir = path.join(analysis.root, ".vscode");
|
|
679
|
+
const settingsPath = path.join(vscodeDir, "extensions.json");
|
|
680
|
+
let currentSettings = {};
|
|
681
|
+
|
|
682
|
+
try {
|
|
683
|
+
const currentSettingsFile = fs.readFileSync(settingsPath, "utf-8");
|
|
684
|
+
if (currentSettingsFile) {
|
|
685
|
+
try {
|
|
686
|
+
currentSettings = JSON.parse(currentSettingsFile);
|
|
687
|
+
} catch (err) {
|
|
688
|
+
logger.warn(
|
|
689
|
+
`Failed to parse VS Code extensions.json found here: ${settingsPath}.${
|
|
690
|
+
err instanceof Error ? `Parse error: ${err.message}` : ""
|
|
691
|
+
}`
|
|
692
|
+
);
|
|
693
|
+
return {
|
|
694
|
+
abort: true,
|
|
695
|
+
};
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
} catch {
|
|
699
|
+
// ignore - dir does not exist (most likely)
|
|
700
|
+
}
|
|
701
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
702
|
+
const currentRecommendations: string[] = (currentSettings as any)
|
|
703
|
+
.recommendations;
|
|
704
|
+
const valBuildIntelliSense = "valbuild.vscode-val-build";
|
|
705
|
+
if (!currentRecommendations.includes(valBuildIntelliSense)) {
|
|
706
|
+
currentSettings = {
|
|
707
|
+
...currentSettings,
|
|
708
|
+
recommendations: (currentRecommendations || []).concat(
|
|
709
|
+
valBuildIntelliSense
|
|
710
|
+
),
|
|
711
|
+
};
|
|
712
|
+
}
|
|
713
|
+
plan.updateVSCodeSettings = {
|
|
714
|
+
path: settingsPath,
|
|
715
|
+
source: JSON.stringify(currentSettings, null, 2),
|
|
716
|
+
};
|
|
717
|
+
} else {
|
|
718
|
+
plan.updateVSCodeSettings = false;
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
{
|
|
723
|
+
const answer = await confirm({
|
|
724
|
+
message: "Include example Val files?",
|
|
725
|
+
default: true,
|
|
726
|
+
});
|
|
727
|
+
if (answer) {
|
|
728
|
+
const exampleDir = path.join(analysis.srcDir, "examples", "val");
|
|
729
|
+
const examplePath = path.join(
|
|
730
|
+
exampleDir,
|
|
731
|
+
"example.val." + (analysis.isJavaScript ? "js" : "ts")
|
|
732
|
+
);
|
|
733
|
+
const exampleImport = path
|
|
734
|
+
.relative(exampleDir, valConfigPath)
|
|
735
|
+
.replace(".js", "")
|
|
736
|
+
.replace(".ts", "");
|
|
737
|
+
if (!analysis.packageJsonDir) {
|
|
738
|
+
throw Error(
|
|
739
|
+
"Could not detect package.json directory! This is a Val bug."
|
|
740
|
+
);
|
|
741
|
+
}
|
|
742
|
+
const exampleModuleId = `/${path
|
|
743
|
+
.relative(analysis.packageJsonDir, examplePath)
|
|
744
|
+
.replace(".val", "")
|
|
745
|
+
.replace(".js", "")
|
|
746
|
+
.replace(".ts", "")}`;
|
|
747
|
+
|
|
748
|
+
plan.includeExample = {
|
|
749
|
+
path: examplePath,
|
|
750
|
+
source: BASIC_EXAMPLE(
|
|
751
|
+
exampleModuleId,
|
|
752
|
+
exampleImport,
|
|
753
|
+
!!analysis.isJavaScript
|
|
754
|
+
),
|
|
755
|
+
};
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
|
|
613
759
|
return plan;
|
|
614
760
|
}
|
|
615
761
|
|
|
@@ -621,17 +767,48 @@ async function execute(plan: Plan) {
|
|
|
621
767
|
return logger.error("Failed to find root directory");
|
|
622
768
|
}
|
|
623
769
|
logger.info("Executing...");
|
|
624
|
-
for (const [key,
|
|
625
|
-
|
|
770
|
+
for (const [key, maybeFileOp] of Object.entries(plan)) {
|
|
771
|
+
if (isFileOp(maybeFileOp)) {
|
|
772
|
+
writeFile(maybeFileOp, plan.root, key.startsWith("update"));
|
|
773
|
+
}
|
|
626
774
|
}
|
|
775
|
+
logger.info(`
|
|
776
|
+
|
|
777
|
+
Val was successfully initialized!
|
|
778
|
+
|
|
779
|
+
Start the application:
|
|
780
|
+
|
|
781
|
+
$ ${chalk.gray("npm run dev")}
|
|
782
|
+
|
|
783
|
+
Open (assumes http://localhost:3000):
|
|
784
|
+
|
|
785
|
+
${chalk.bgBlack.hex("#37cd99").underline(`http://localhost:3000/val`)}
|
|
786
|
+
|
|
787
|
+
When you want to enable editor support, import the project by opening the following link:
|
|
788
|
+
|
|
789
|
+
${chalk.bgBlack
|
|
790
|
+
.hex("#37cd99")
|
|
791
|
+
.underline(
|
|
792
|
+
`https://app.val.build/orgs/new${
|
|
793
|
+
plan.gitRemote
|
|
794
|
+
? `?org=${encodeURIComponent(
|
|
795
|
+
plan.gitRemote.owner
|
|
796
|
+
)}&owner=${encodeURIComponent(
|
|
797
|
+
plan.gitRemote.owner
|
|
798
|
+
)}&repo=${encodeURIComponent(plan.gitRemote.repo)}`
|
|
799
|
+
: ""
|
|
800
|
+
}`
|
|
801
|
+
)}
|
|
802
|
+
|
|
803
|
+
`);
|
|
627
804
|
}
|
|
628
805
|
|
|
629
806
|
function writeFile(
|
|
630
|
-
fileOp:
|
|
807
|
+
fileOp: FileOp | undefined,
|
|
631
808
|
rootDir: string,
|
|
632
809
|
isUpdate: boolean
|
|
633
810
|
) {
|
|
634
|
-
if (fileOp
|
|
811
|
+
if (fileOp) {
|
|
635
812
|
fs.mkdirSync(path.dirname(fileOp.path), { recursive: true });
|
|
636
813
|
fs.writeFileSync(fileOp.path, fileOp.source);
|
|
637
814
|
logger.info(
|
|
@@ -667,3 +844,16 @@ function getGitStatusIsClean(gitStatus: StatusResult): Analysis["isGitClean"] {
|
|
|
667
844
|
}
|
|
668
845
|
return false;
|
|
669
846
|
}
|
|
847
|
+
|
|
848
|
+
function isFileOp(maybeFileOp: unknown): maybeFileOp is FileOp {
|
|
849
|
+
return (
|
|
850
|
+
typeof maybeFileOp !== "boolean" &&
|
|
851
|
+
typeof maybeFileOp !== "string" &&
|
|
852
|
+
typeof maybeFileOp === "object" &&
|
|
853
|
+
!!maybeFileOp &&
|
|
854
|
+
"path" in maybeFileOp &&
|
|
855
|
+
"source" in maybeFileOp &&
|
|
856
|
+
typeof maybeFileOp.path === "string" &&
|
|
857
|
+
typeof maybeFileOp.source === "string"
|
|
858
|
+
);
|
|
859
|
+
}
|
package/src/logger.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
|
|
3
3
|
export function error(message: string) {
|
|
4
|
-
console.error(chalk.red("❌ ERROR: ") + message);
|
|
4
|
+
console.error(chalk.red(" ❌ ERROR: ") + message);
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
export function warn(message: string) {
|
|
8
|
-
console.error(chalk.yellow("⚠️ WARN:"
|
|
8
|
+
console.error(chalk.yellow(" ⚠️ WARN:" + message));
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export function info(
|
|
@@ -17,7 +17,7 @@ export function info(
|
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
19
19
|
if (opts.isGood) {
|
|
20
|
-
console.log(chalk.
|
|
20
|
+
console.log(chalk.hex("#37cd99")(" V") + message);
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
23
|
console.log(message);
|