@featurevisor/core 0.52.0 → 0.53.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.
Files changed (63) hide show
  1. package/.eslintcache +1 -1
  2. package/CHANGELOG.md +19 -0
  3. package/coverage/clover.xml +2 -2
  4. package/coverage/lcov-report/index.html +1 -1
  5. package/coverage/lcov-report/lib/builder/allocator.js.html +1 -1
  6. package/coverage/lcov-report/lib/builder/index.html +1 -1
  7. package/coverage/lcov-report/lib/builder/traffic.js.html +1 -1
  8. package/coverage/lcov-report/src/builder/allocator.ts.html +1 -1
  9. package/coverage/lcov-report/src/builder/index.html +1 -1
  10. package/coverage/lcov-report/src/builder/traffic.ts.html +1 -1
  11. package/lib/find-duplicate-segments/findDuplicateSegments.d.ts +3 -0
  12. package/lib/find-duplicate-segments/findDuplicateSegments.js +27 -0
  13. package/lib/find-duplicate-segments/findDuplicateSegments.js.map +1 -0
  14. package/lib/find-duplicate-segments/index.d.ts +2 -0
  15. package/lib/find-duplicate-segments/index.js +19 -0
  16. package/lib/find-duplicate-segments/index.js.map +1 -0
  17. package/lib/index.d.ts +1 -0
  18. package/lib/index.js +1 -0
  19. package/lib/index.js.map +1 -1
  20. package/lib/site/exportSite.d.ts +2 -0
  21. package/lib/site/exportSite.js +34 -0
  22. package/lib/site/exportSite.js.map +1 -0
  23. package/lib/site/generateHistory.d.ts +3 -0
  24. package/lib/site/generateHistory.js +76 -0
  25. package/lib/site/generateHistory.js.map +1 -0
  26. package/lib/site/generateSiteSearchIndex.d.ts +4 -0
  27. package/lib/site/generateSiteSearchIndex.js +141 -0
  28. package/lib/site/generateSiteSearchIndex.js.map +1 -0
  29. package/lib/site/getLastModifiedFromHistory.d.ts +2 -0
  30. package/lib/site/getLastModifiedFromHistory.js +19 -0
  31. package/lib/site/getLastModifiedFromHistory.js.map +1 -0
  32. package/lib/site/getOwnerAndRepoFromUrl.d.ts +4 -0
  33. package/lib/site/getOwnerAndRepoFromUrl.js +21 -0
  34. package/lib/site/getOwnerAndRepoFromUrl.js.map +1 -0
  35. package/lib/site/getRelativePaths.d.ts +6 -0
  36. package/lib/site/getRelativePaths.js +16 -0
  37. package/lib/site/getRelativePaths.js.map +1 -0
  38. package/lib/site/getRepoDetails.d.ts +8 -0
  39. package/lib/site/getRepoDetails.js +49 -0
  40. package/lib/site/getRepoDetails.js.map +1 -0
  41. package/lib/site/index.d.ts +2 -0
  42. package/lib/site/index.js +19 -0
  43. package/lib/site/index.js.map +1 -0
  44. package/lib/site/serveSite.d.ts +2 -0
  45. package/lib/site/serveSite.js +55 -0
  46. package/lib/site/serveSite.js.map +1 -0
  47. package/package.json +5 -5
  48. package/src/find-duplicate-segments/findDuplicateSegments.ts +33 -0
  49. package/src/find-duplicate-segments/index.ts +21 -0
  50. package/src/index.ts +1 -0
  51. package/src/site/exportSite.ts +53 -0
  52. package/src/site/generateHistory.ts +101 -0
  53. package/src/site/generateSiteSearchIndex.ts +203 -0
  54. package/src/site/getLastModifiedFromHistory.ts +21 -0
  55. package/src/site/getOwnerAndRepoFromUrl.ts +17 -0
  56. package/src/site/getRelativePaths.ts +24 -0
  57. package/src/site/getRepoDetails.ts +62 -0
  58. package/src/site/index.ts +2 -0
  59. package/src/site/serveSite.ts +60 -0
  60. package/lib/site.d.ts +0 -16
  61. package/lib/site.js +0 -368
  62. package/lib/site.js.map +0 -1
  63. package/src/site.ts +0 -515
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getLastModifiedFromHistory = void 0;
4
+ function getLastModifiedFromHistory(fullHistory, type, key) {
5
+ var lastModified = fullHistory.find(function (entry) {
6
+ return entry.entities.find(function (entity) {
7
+ return entity.type === type && entity.key === key;
8
+ });
9
+ });
10
+ if (lastModified) {
11
+ return {
12
+ commit: lastModified.commit,
13
+ timestamp: lastModified.timestamp,
14
+ author: lastModified.author,
15
+ };
16
+ }
17
+ }
18
+ exports.getLastModifiedFromHistory = getLastModifiedFromHistory;
19
+ //# sourceMappingURL=getLastModifiedFromHistory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getLastModifiedFromHistory.js","sourceRoot":"","sources":["../../src/site/getLastModifiedFromHistory.ts"],"names":[],"mappings":";;;AAEA,SAAgB,0BAA0B,CACxC,WAA2B,EAC3B,IAAI,EACJ,GAAG;IAEH,IAAM,YAAY,GAAG,WAAW,CAAC,IAAI,CAAC,UAAC,KAAK;QAC1C,OAAO,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAC,MAAM;YAChC,OAAO,MAAM,CAAC,IAAI,KAAK,IAAI,IAAI,MAAM,CAAC,GAAG,KAAK,GAAG,CAAC;QACpD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAI,YAAY,EAAE;QAChB,OAAO;YACL,MAAM,EAAE,YAAY,CAAC,MAAM;YAC3B,SAAS,EAAE,YAAY,CAAC,SAAS;YACjC,MAAM,EAAE,YAAY,CAAC,MAAM;SAC5B,CAAC;KACH;AACH,CAAC;AAlBD,gEAkBC"}
@@ -0,0 +1,4 @@
1
+ export declare function getOwnerAndRepoFromUrl(url: string): {
2
+ owner: string;
3
+ repo: string;
4
+ };
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getOwnerAndRepoFromUrl = void 0;
4
+ function getOwnerAndRepoFromUrl(url) {
5
+ var owner;
6
+ var repo;
7
+ if (url.startsWith("https://")) {
8
+ var parts = url.split("/");
9
+ repo = parts.pop().replace(".git", "");
10
+ owner = parts.pop();
11
+ }
12
+ else if (url.startsWith("git@")) {
13
+ var urlParts = url.split(":");
14
+ var parts = urlParts[1].split("/");
15
+ repo = parts.pop().replace(".git", "");
16
+ owner = parts.pop();
17
+ }
18
+ return { owner: owner, repo: repo };
19
+ }
20
+ exports.getOwnerAndRepoFromUrl = getOwnerAndRepoFromUrl;
21
+ //# sourceMappingURL=getOwnerAndRepoFromUrl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getOwnerAndRepoFromUrl.js","sourceRoot":"","sources":["../../src/site/getOwnerAndRepoFromUrl.ts"],"names":[],"mappings":";;;AAAA,SAAgB,sBAAsB,CAAC,GAAW;IAChD,IAAI,KAAK,CAAC;IACV,IAAI,IAAI,CAAC;IAET,IAAI,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE;QAC9B,IAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,GAAI,KAAK,CAAC,GAAG,EAAa,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACnD,KAAK,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC;KACrB;SAAM,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE;QACjC,IAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAChC,IAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,GAAI,KAAK,CAAC,GAAG,EAAa,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACnD,KAAK,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC;KACrB;IAED,OAAO,EAAE,KAAK,OAAA,EAAE,IAAI,MAAA,EAAE,CAAC;AACzB,CAAC;AAhBD,wDAgBC"}
@@ -0,0 +1,6 @@
1
+ import { ProjectConfig } from "../config";
2
+ export declare function getRelativePaths(rootDirectoryPath: any, projectConfig: ProjectConfig): {
3
+ relativeFeaturesPath: string;
4
+ relativeSegmentsPath: string;
5
+ relativeAttributesPath: string;
6
+ };
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getRelativePaths = void 0;
4
+ var path = require("path");
5
+ function getRelativePaths(rootDirectoryPath, projectConfig) {
6
+ var relativeFeaturesPath = path.relative(rootDirectoryPath, projectConfig.featuresDirectoryPath);
7
+ var relativeSegmentsPath = path.relative(rootDirectoryPath, projectConfig.segmentsDirectoryPath);
8
+ var relativeAttributesPath = path.relative(rootDirectoryPath, projectConfig.attributesDirectoryPath);
9
+ return {
10
+ relativeFeaturesPath: relativeFeaturesPath,
11
+ relativeSegmentsPath: relativeSegmentsPath,
12
+ relativeAttributesPath: relativeAttributesPath,
13
+ };
14
+ }
15
+ exports.getRelativePaths = getRelativePaths;
16
+ //# sourceMappingURL=getRelativePaths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getRelativePaths.js","sourceRoot":"","sources":["../../src/site/getRelativePaths.ts"],"names":[],"mappings":";;;AAAA,2BAA6B;AAI7B,SAAgB,gBAAgB,CAAC,iBAAiB,EAAE,aAA4B;IAC9E,IAAM,oBAAoB,GAAG,IAAI,CAAC,QAAQ,CACxC,iBAAiB,EACjB,aAAa,CAAC,qBAAqB,CACpC,CAAC;IACF,IAAM,oBAAoB,GAAG,IAAI,CAAC,QAAQ,CACxC,iBAAiB,EACjB,aAAa,CAAC,qBAAqB,CACpC,CAAC;IACF,IAAM,sBAAsB,GAAG,IAAI,CAAC,QAAQ,CAC1C,iBAAiB,EACjB,aAAa,CAAC,uBAAuB,CACtC,CAAC;IAEF,OAAO;QACL,oBAAoB,sBAAA;QACpB,oBAAoB,sBAAA;QACpB,sBAAsB,wBAAA;KACvB,CAAC;AACJ,CAAC;AAnBD,4CAmBC"}
@@ -0,0 +1,8 @@
1
+ export interface RepoDetails {
2
+ branch: string;
3
+ remoteUrl: string;
4
+ blobUrl: string;
5
+ commitUrl: string;
6
+ topLevelPath: string;
7
+ }
8
+ export declare function getRepoDetails(): RepoDetails | undefined;
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getRepoDetails = void 0;
4
+ var child_process_1 = require("child_process");
5
+ var getOwnerAndRepoFromUrl_1 = require("./getOwnerAndRepoFromUrl");
6
+ function getRepoDetails() {
7
+ try {
8
+ var topLevelPathOutput = (0, child_process_1.execSync)("git rev-parse --show-toplevel");
9
+ var topLevelPath = topLevelPathOutput.toString().trim();
10
+ var remoteUrlOutput = (0, child_process_1.execSync)("git remote get-url origin");
11
+ var remoteUrl = remoteUrlOutput.toString().trim();
12
+ var branchOutput = (0, child_process_1.execSync)("git rev-parse --abbrev-ref HEAD");
13
+ var branch = branchOutput.toString().trim();
14
+ if (!remoteUrl || !branch) {
15
+ return;
16
+ }
17
+ var _a = (0, getOwnerAndRepoFromUrl_1.getOwnerAndRepoFromUrl)(remoteUrl), owner = _a.owner, repo = _a.repo;
18
+ if (!owner || !repo) {
19
+ return;
20
+ }
21
+ var blobUrl = void 0;
22
+ var commitUrl = void 0;
23
+ if (remoteUrl.indexOf("github.com") > -1) {
24
+ blobUrl = "https://github.com/".concat(owner, "/").concat(repo, "/blob/").concat(branch, "/{{blobPath}}");
25
+ commitUrl = "https://github.com/".concat(owner, "/").concat(repo, "/commit/{{hash}}");
26
+ }
27
+ else if (remoteUrl.indexOf("bitbucket.org") > -1) {
28
+ blobUrl = "https://bitbucket.org/".concat(owner, "/").concat(repo, "/src/").concat(branch, "/{{blobPath}}");
29
+ commitUrl = "https://bitbucket.org/".concat(owner, "/").concat(repo, "/commits/{{hash}}");
30
+ }
31
+ if (!blobUrl || !commitUrl) {
32
+ return;
33
+ }
34
+ return {
35
+ branch: branch,
36
+ remoteUrl: remoteUrl,
37
+ blobUrl: blobUrl,
38
+ commitUrl: commitUrl,
39
+ topLevelPath: topLevelPath,
40
+ };
41
+ }
42
+ catch (e) {
43
+ console.error(e);
44
+ return;
45
+ }
46
+ return;
47
+ }
48
+ exports.getRepoDetails = getRepoDetails;
49
+ //# sourceMappingURL=getRepoDetails.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getRepoDetails.js","sourceRoot":"","sources":["../../src/site/getRepoDetails.ts"],"names":[],"mappings":";;;AAAA,+CAAyC;AAEzC,mEAAkE;AAUlE,SAAgB,cAAc;IAC5B,IAAI;QACF,IAAM,kBAAkB,GAAG,IAAA,wBAAQ,EAAC,+BAA+B,CAAC,CAAC;QACrE,IAAM,YAAY,GAAG,kBAAkB,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC;QAE1D,IAAM,eAAe,GAAG,IAAA,wBAAQ,EAAC,2BAA2B,CAAC,CAAC;QAC9D,IAAM,SAAS,GAAG,eAAe,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC;QAEpD,IAAM,YAAY,GAAG,IAAA,wBAAQ,EAAC,iCAAiC,CAAC,CAAC;QACjE,IAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC;QAE9C,IAAI,CAAC,SAAS,IAAI,CAAC,MAAM,EAAE;YACzB,OAAO;SACR;QAEK,IAAA,KAAkB,IAAA,+CAAsB,EAAC,SAAS,CAAC,EAAjD,KAAK,WAAA,EAAE,IAAI,UAAsC,CAAC;QAE1D,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,EAAE;YACnB,OAAO;SACR;QAED,IAAI,OAAO,SAAA,CAAC;QACZ,IAAI,SAAS,SAAA,CAAC;QAEd,IAAI,SAAS,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE;YACxC,OAAO,GAAG,6BAAsB,KAAK,cAAI,IAAI,mBAAS,MAAM,kBAAe,CAAC;YAC5E,SAAS,GAAG,6BAAsB,KAAK,cAAI,IAAI,qBAAkB,CAAC;SACnE;aAAM,IAAI,SAAS,CAAC,OAAO,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,EAAE;YAClD,OAAO,GAAG,gCAAyB,KAAK,cAAI,IAAI,kBAAQ,MAAM,kBAAe,CAAC;YAC9E,SAAS,GAAG,gCAAyB,KAAK,cAAI,IAAI,sBAAmB,CAAC;SACvE;QAED,IAAI,CAAC,OAAO,IAAI,CAAC,SAAS,EAAE;YAC1B,OAAO;SACR;QAED,OAAO;YACL,MAAM,QAAA;YACN,SAAS,WAAA;YACT,OAAO,SAAA;YACP,SAAS,WAAA;YACT,YAAY,cAAA;SACb,CAAC;KACH;IAAC,OAAO,CAAC,EAAE;QACV,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACjB,OAAO;KACR;IAED,OAAO;AACT,CAAC;AAjDD,wCAiDC"}
@@ -0,0 +1,2 @@
1
+ export * from "./exportSite";
2
+ export * from "./serveSite";
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./exportSite"), exports);
18
+ __exportStar(require("./serveSite"), exports);
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/site/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+CAA6B;AAC7B,8CAA4B"}
@@ -0,0 +1,2 @@
1
+ import { ProjectConfig } from "../config";
2
+ export declare function serveSite(rootDirectoryPath: string, projectConfig: ProjectConfig, options?: any): void;
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.serveSite = void 0;
4
+ var fs = require("fs");
5
+ var path = require("path");
6
+ var http = require("http");
7
+ function serveSite(rootDirectoryPath, projectConfig, options) {
8
+ if (options === void 0) { options = {}; }
9
+ var port = options.p || 3000;
10
+ http
11
+ .createServer(function (request, response) {
12
+ var requestedUrl = request.url;
13
+ var filePath = requestedUrl === "/"
14
+ ? path.join(projectConfig.siteExportDirectoryPath, "index.html")
15
+ : path.join(projectConfig.siteExportDirectoryPath, requestedUrl);
16
+ console.log("requesting: " + filePath + "");
17
+ var extname = path.extname(filePath);
18
+ var contentType = "text/html";
19
+ switch (extname) {
20
+ case ".js":
21
+ contentType = "text/javascript";
22
+ break;
23
+ case ".css":
24
+ contentType = "text/css";
25
+ break;
26
+ case ".json":
27
+ contentType = "application/json";
28
+ break;
29
+ case ".png":
30
+ contentType = "image/png";
31
+ break;
32
+ }
33
+ fs.readFile(filePath, function (error, content) {
34
+ if (error) {
35
+ if (error.code == "ENOENT") {
36
+ response.writeHead(404, { "Content-Type": "text/html" });
37
+ response.end("404 Not Found", "utf-8");
38
+ }
39
+ else {
40
+ response.writeHead(500);
41
+ response.end("Error 500: " + error.code);
42
+ response.end();
43
+ }
44
+ }
45
+ else {
46
+ response.writeHead(200, { "Content-Type": contentType });
47
+ response.end(content, "utf-8");
48
+ }
49
+ });
50
+ })
51
+ .listen(port);
52
+ console.log("Server running at http://127.0.0.1:".concat(port, "/"));
53
+ }
54
+ exports.serveSite = serveSite;
55
+ //# sourceMappingURL=serveSite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serveSite.js","sourceRoot":"","sources":["../../src/site/serveSite.ts"],"names":[],"mappings":";;;AAAA,uBAAyB;AACzB,2BAA6B;AAC7B,2BAA6B;AAI7B,SAAgB,SAAS,CACvB,iBAAyB,EACzB,aAA4B,EAC5B,OAAiB;IAAjB,wBAAA,EAAA,YAAiB;IAEjB,IAAM,IAAI,GAAG,OAAO,CAAC,CAAC,IAAI,IAAI,CAAC;IAE/B,IAAI;SACD,YAAY,CAAC,UAAU,OAAO,EAAE,QAAQ;QACvC,IAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC;QACjC,IAAM,QAAQ,GACZ,YAAY,KAAK,GAAG;YAClB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,uBAAuB,EAAE,YAAY,CAAC;YAChE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,uBAAuB,EAAE,YAAsB,CAAC,CAAC;QAE/E,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,QAAQ,GAAG,EAAE,CAAC,CAAC;QAE5C,IAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACvC,IAAI,WAAW,GAAG,WAAW,CAAC;QAC9B,QAAQ,OAAO,EAAE;YACf,KAAK,KAAK;gBACR,WAAW,GAAG,iBAAiB,CAAC;gBAChC,MAAM;YACR,KAAK,MAAM;gBACT,WAAW,GAAG,UAAU,CAAC;gBACzB,MAAM;YACR,KAAK,OAAO;gBACV,WAAW,GAAG,kBAAkB,CAAC;gBACjC,MAAM;YACR,KAAK,MAAM;gBACT,WAAW,GAAG,WAAW,CAAC;gBAC1B,MAAM;SACT;QAED,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU,KAAK,EAAE,OAAO;YAC5C,IAAI,KAAK,EAAE;gBACT,IAAI,KAAK,CAAC,IAAI,IAAI,QAAQ,EAAE;oBAC1B,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC,CAAC;oBACzD,QAAQ,CAAC,GAAG,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;iBACxC;qBAAM;oBACL,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;oBACxB,QAAQ,CAAC,GAAG,CAAC,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;oBACzC,QAAQ,CAAC,GAAG,EAAE,CAAC;iBAChB;aACF;iBAAM;gBACL,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC,CAAC;gBACzD,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;aAChC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;SACD,MAAM,CAAC,IAAI,CAAC,CAAC;IAEhB,OAAO,CAAC,GAAG,CAAC,6CAAsC,IAAI,MAAG,CAAC,CAAC;AAC7D,CAAC;AArDD,8BAqDC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@featurevisor/core",
3
- "version": "0.52.0",
3
+ "version": "0.53.0",
4
4
  "description": "Core package of Featurevisor for Node.js usage",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -44,9 +44,9 @@
44
44
  },
45
45
  "license": "MIT",
46
46
  "dependencies": {
47
- "@featurevisor/sdk": "^0.52.0",
48
- "@featurevisor/site": "^0.52.0",
49
- "@featurevisor/types": "^0.52.0",
47
+ "@featurevisor/sdk": "^0.53.0",
48
+ "@featurevisor/site": "^0.53.0",
49
+ "@featurevisor/types": "^0.53.0",
50
50
  "axios": "^1.3.4",
51
51
  "joi": "^17.8.3",
52
52
  "js-yaml": "^4.1.0",
@@ -57,5 +57,5 @@
57
57
  "@types/js-yaml": "^4.0.5",
58
58
  "@types/tar": "^6.1.4"
59
59
  },
60
- "gitHead": "9bc6c82fa09d23dd9486c44b51474758c3e8c8bb"
60
+ "gitHead": "7961266cf6ea97eea9ac6fbbd82918abcd50e07e"
61
61
  }
@@ -0,0 +1,33 @@
1
+ import * as crypto from "crypto";
2
+
3
+ import { SegmentKey } from "@featurevisor/types";
4
+
5
+ import { Datasource } from "../datasource";
6
+
7
+ export function findDuplicateSegments(datasource: Datasource): SegmentKey[][] {
8
+ const segmentsWithHash = datasource.listSegments().map((segmentKey) => {
9
+ const segment = datasource.readSegment(segmentKey);
10
+ const conditions = JSON.stringify(segment.conditions);
11
+ const hash = crypto.createHash("sha256").update(conditions).digest("hex");
12
+
13
+ return {
14
+ segmentKey,
15
+ hash,
16
+ };
17
+ });
18
+
19
+ const groupedSegments: { [hash: string]: SegmentKey[] } = segmentsWithHash.reduce(
20
+ (acc, { segmentKey, hash }) => {
21
+ if (!acc[hash]) {
22
+ acc[hash] = [];
23
+ }
24
+ acc[hash].push(segmentKey);
25
+ return acc;
26
+ },
27
+ {},
28
+ );
29
+
30
+ const result = Object.values(groupedSegments).filter((segmentKeys) => segmentKeys.length > 1);
31
+
32
+ return result;
33
+ }
@@ -0,0 +1,21 @@
1
+ import { Datasource } from "../datasource";
2
+ import { ProjectConfig } from "../config";
3
+
4
+ import { findDuplicateSegments } from "./findDuplicateSegments";
5
+
6
+ export function findDuplicateSegmentsInProject(rootDirectoryPath, projectConfig: ProjectConfig) {
7
+ const datasource = new Datasource(projectConfig);
8
+
9
+ const duplicates = findDuplicateSegments(datasource);
10
+
11
+ if (duplicates.length === 0) {
12
+ console.log("No duplicate segments found");
13
+ return;
14
+ }
15
+
16
+ console.log(`Found ${duplicates.length} duplicates:\n`);
17
+
18
+ duplicates.forEach((segmentKeys) => {
19
+ console.log(` - ${segmentKeys.join(", ")}`);
20
+ });
21
+ }
package/src/index.ts CHANGED
@@ -6,3 +6,4 @@ export * from "./init";
6
6
  export * from "./site";
7
7
  export * from "./generate-code";
8
8
  export * from "./restore";
9
+ export * from "./find-duplicate-segments";
@@ -0,0 +1,53 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+
4
+ import * as mkdirp from "mkdirp";
5
+
6
+ import { ProjectConfig } from "../config";
7
+
8
+ import { generateHistory } from "./generateHistory";
9
+ import { getRepoDetails } from "./getRepoDetails";
10
+ import { generateSiteSearchIndex } from "./generateSiteSearchIndex";
11
+
12
+ export function exportSite(rootDirectoryPath: string, projectConfig: ProjectConfig) {
13
+ const hasError = false;
14
+
15
+ mkdirp.sync(projectConfig.siteExportDirectoryPath);
16
+
17
+ const sitePackagePath = path.dirname(require.resolve("@featurevisor/site/package.json"));
18
+
19
+ // copy site dist
20
+ const siteDistPath = path.join(sitePackagePath, "dist");
21
+ fs.cpSync(siteDistPath, projectConfig.siteExportDirectoryPath, { recursive: true });
22
+
23
+ const sitePublicPath = path.join(sitePackagePath, "public");
24
+ fs.cpSync(sitePublicPath, projectConfig.siteExportDirectoryPath, { recursive: true });
25
+
26
+ console.log("Site dist copied to:", projectConfig.siteExportDirectoryPath);
27
+
28
+ // generate history
29
+ const fullHistory = generateHistory(rootDirectoryPath, projectConfig);
30
+
31
+ // site search index
32
+ const repoDetails = getRepoDetails();
33
+ const searchIndex = generateSiteSearchIndex(
34
+ rootDirectoryPath,
35
+ projectConfig,
36
+ fullHistory,
37
+ repoDetails,
38
+ );
39
+ const searchIndexFilePath = path.join(projectConfig.siteExportDirectoryPath, "search-index.json");
40
+ fs.writeFileSync(searchIndexFilePath, JSON.stringify(searchIndex));
41
+ console.log(`Site search index written at: ${searchIndexFilePath}`);
42
+
43
+ // copy datafiles
44
+ fs.cpSync(
45
+ projectConfig.outputDirectoryPath,
46
+ path.join(projectConfig.siteExportDirectoryPath, "datafiles"),
47
+ { recursive: true },
48
+ );
49
+
50
+ // @TODO: replace placeoholders in index.html
51
+
52
+ return hasError;
53
+ }
@@ -0,0 +1,101 @@
1
+ import * as path from "path";
2
+ import * as fs from "fs";
3
+ import { execSync } from "child_process";
4
+
5
+ import { HistoryEntry } from "@featurevisor/types";
6
+
7
+ import { ProjectConfig } from "../config";
8
+
9
+ import { getRelativePaths } from "./getRelativePaths";
10
+
11
+ export function generateHistory(rootDirectoryPath, projectConfig: ProjectConfig): HistoryEntry[] {
12
+ try {
13
+ // raw history
14
+ const rawHistoryFilePath = path.join(projectConfig.siteExportDirectoryPath, "history-raw.txt");
15
+
16
+ const { relativeFeaturesPath, relativeSegmentsPath, relativeAttributesPath } = getRelativePaths(
17
+ rootDirectoryPath,
18
+ projectConfig,
19
+ );
20
+
21
+ const separator = "|";
22
+
23
+ const cmd = `git log --name-only --pretty=format:"%h${separator}%an${separator}%aI" --no-merges --relative -- ${relativeFeaturesPath} ${relativeSegmentsPath} ${relativeAttributesPath} > ${rawHistoryFilePath}`;
24
+ execSync(cmd);
25
+
26
+ console.log(`History (raw) generated at: ${rawHistoryFilePath}`);
27
+
28
+ // structured history
29
+ const rawHistory = fs.readFileSync(rawHistoryFilePath, "utf8");
30
+
31
+ const fullHistory: HistoryEntry[] = [];
32
+
33
+ let entry: HistoryEntry = {
34
+ commit: "",
35
+ author: "",
36
+ timestamp: "",
37
+ entities: [],
38
+ };
39
+
40
+ rawHistory.split("\n").forEach((line, index) => {
41
+ if (index === 0 && line.length === 0) {
42
+ // no history found
43
+ return;
44
+ }
45
+
46
+ if (index > 0 && line.length === 0) {
47
+ // commit finished
48
+ fullHistory.push(entry);
49
+
50
+ return;
51
+ }
52
+
53
+ if (line.indexOf(separator) > -1) {
54
+ // commit line
55
+ const parts = line.split("|");
56
+
57
+ entry = {
58
+ commit: parts[0],
59
+ author: parts[1],
60
+ timestamp: parts[2],
61
+ entities: [],
62
+ };
63
+ } else {
64
+ // file line
65
+ const lineSplit = line.split(path.sep);
66
+ const fileName = lineSplit.pop() as string;
67
+ const relativeDir = lineSplit.join(path.sep);
68
+
69
+ const key = fileName.replace("." + projectConfig.parser, "");
70
+
71
+ let type = "feature" as "attribute" | "segment" | "feature";
72
+
73
+ if (relativeDir === relativeSegmentsPath) {
74
+ type = "segment";
75
+ } else if (relativeDir === relativeAttributesPath) {
76
+ type = "attribute";
77
+ }
78
+
79
+ entry.entities.push({
80
+ type,
81
+ key,
82
+ });
83
+ }
84
+ });
85
+
86
+ const fullHistoryFilePath = path.join(
87
+ projectConfig.siteExportDirectoryPath,
88
+ "history-full.json",
89
+ );
90
+ fs.writeFileSync(fullHistoryFilePath, JSON.stringify(fullHistory));
91
+ console.log(`History (full) generated at: ${fullHistoryFilePath}`);
92
+
93
+ return fullHistory;
94
+ } catch (error) {
95
+ console.error(
96
+ `Error when generating history from git: ${error.status}\n${error.stderr.toString()}`,
97
+ );
98
+
99
+ return [];
100
+ }
101
+ }