@static-suite/static-suite-data-server 1.0.3 → 1.0.5
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/dist/http/routes/diff.d.ts +7 -0
- package/dist/http/routes/diff.d.ts.map +1 -0
- package/dist/http/routes/diff.js +40 -0
- package/dist/http/routes/home.d.ts.map +1 -1
- package/dist/http/routes/home.js +1 -0
- package/dist/http/routes/index.d.ts.map +1 -1
- package/dist/http/routes/index.js +5 -0
- package/dist/http/views/diffIndex.pug +14 -0
- package/dist/lib/dataServer.d.ts.map +1 -1
- package/dist/lib/dataServer.js +11 -0
- package/dist/lib/store/diff/diff.types.d.ts.map +1 -1
- package/dist/lib/store/diff/diffManager.d.ts.map +1 -1
- package/dist/lib/store/dump/dump.types.d.ts +4 -0
- package/dist/lib/store/dump/dump.types.d.ts.map +1 -1
- package/dist/lib/store/dump/dumpIndexHelper.d.ts +13 -0
- package/dist/lib/store/dump/dumpIndexHelper.d.ts.map +1 -0
- package/dist/lib/store/dump/dumpIndexHelper.js +111 -0
- package/dist/lib/store/dump/dumpManager.d.ts.map +1 -1
- package/dist/lib/store/dump/dumpManager.js +37 -48
- package/dist/lib/store/dump/dumpMetadataHelper.d.ts.map +1 -1
- package/dist/lib/store/dump/dumpMetadataHelper.js +2 -1
- package/dist/lib/utils/fs/fsUtils.js +1 -1
- package/dist/lib/utils/string/stringUtils.d.ts +6 -0
- package/dist/lib/utils/string/stringUtils.d.ts.map +1 -1
- package/dist/lib/utils/string/stringUtils.js +8 -1
- package/package.json +4 -4
- package/src/http/routes/diff.ts +47 -0
- package/src/http/routes/home.ts +1 -0
- package/src/http/routes/index.ts +5 -0
- package/src/http/routes/subset.ts +1 -1
- package/src/http/views/diffIndex.pug +14 -0
- package/src/lib/dataServer.ts +17 -1
- package/src/lib/store/diff/diff.types.ts +1 -0
- package/src/lib/store/diff/diffManager.ts +1 -0
- package/src/lib/store/dump/dump.types.ts +5 -0
- package/src/lib/store/dump/dumpIndexHelper.ts +132 -0
- package/src/lib/store/dump/dumpManager.ts +53 -58
- package/src/lib/store/dump/dumpMetadataHelper.ts +2 -1
- package/src/lib/utils/fs/fsUtils.ts +1 -2
- package/src/lib/utils/string/stringUtils.ts +8 -0
- package/tsconfig.json +2 -2
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Request, Response } from 'express';
|
|
2
|
+
declare const diffIndex: (req: Request, res: Response) => void;
|
|
3
|
+
declare const diffIncremental: (req: Request, res: Response) => void;
|
|
4
|
+
declare const diffFull: (req: Request, res: Response) => void;
|
|
5
|
+
declare const diffReset: (req: Request, res: Response) => void;
|
|
6
|
+
export { diffIndex, diffIncremental, diffFull, diffReset };
|
|
7
|
+
//# sourceMappingURL=diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../../src/http/routes/diff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAI5C,QAAA,MAAM,SAAS,GAAI,KAAK,OAAO,EAAE,KAAK,QAAQ,KAAG,IAShD,CAAC;AAeF,QAAA,MAAM,eAAe,GAAI,KAAK,OAAO,EAAE,KAAK,QAAQ,KAAG,IAEtD,CAAC;AAEF,QAAA,MAAM,QAAQ,GAAI,KAAK,OAAO,EAAE,KAAK,QAAQ,KAAG,IAE/C,CAAC;AAEF,QAAA,MAAM,SAAS,GAAI,KAAK,OAAO,EAAE,KAAK,QAAQ,KAAG,IAQhD,CAAC;AAEF,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.diffReset = exports.diffFull = exports.diffIncremental = exports.diffIndex = void 0;
|
|
4
|
+
const diff_1 = require("../../lib/store/diff");
|
|
5
|
+
const object_1 = require("../../lib/utils/object");
|
|
6
|
+
const diffIndex = (req, res) => {
|
|
7
|
+
res.render('diffIndex', {
|
|
8
|
+
links: {
|
|
9
|
+
'/diff/incremental': 'Execute an incremental dump',
|
|
10
|
+
'/diff/full': 'Execute a full dump',
|
|
11
|
+
'/diff/reset': 'Clears intermediate changes tracked by dependency manager',
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
exports.diffIndex = diffIndex;
|
|
16
|
+
const diffAction = (req, res, incremental) => {
|
|
17
|
+
const diff = diff_1.diffManager.getDiff({ incremental });
|
|
18
|
+
const diffAsJson = (0, object_1.jsonify)(diff);
|
|
19
|
+
res.status(200);
|
|
20
|
+
res.set({ 'Content-Type': 'application/json' });
|
|
21
|
+
res.send(diffAsJson);
|
|
22
|
+
};
|
|
23
|
+
const diffIncremental = (req, res) => {
|
|
24
|
+
diffAction(req, res, true);
|
|
25
|
+
};
|
|
26
|
+
exports.diffIncremental = diffIncremental;
|
|
27
|
+
const diffFull = (req, res) => {
|
|
28
|
+
diffAction(req, res, false);
|
|
29
|
+
};
|
|
30
|
+
exports.diffFull = diffFull;
|
|
31
|
+
const diffReset = (req, res) => {
|
|
32
|
+
const args = req.query;
|
|
33
|
+
if (args?.uniqueId) {
|
|
34
|
+
diff_1.diffManager.reset(args.uniqueId);
|
|
35
|
+
}
|
|
36
|
+
res.status(200);
|
|
37
|
+
res.set({ 'Content-Type': 'application/json' });
|
|
38
|
+
res.send({ status: 'done' });
|
|
39
|
+
};
|
|
40
|
+
exports.diffReset = diffReset;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"home.d.ts","sourceRoot":"","sources":["../../../src/http/routes/home.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE5C,eAAO,MAAM,IAAI,GAAI,KAAK,OAAO,EAAE,KAAK,QAAQ,KAAG,
|
|
1
|
+
{"version":3,"file":"home.d.ts","sourceRoot":"","sources":["../../../src/http/routes/home.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE5C,eAAO,MAAM,IAAI,GAAI,KAAK,OAAO,EAAE,KAAK,QAAQ,KAAG,IAclD,CAAC"}
|
package/dist/http/routes/home.js
CHANGED
|
@@ -6,6 +6,7 @@ const home = (req, res) => {
|
|
|
6
6
|
links: {
|
|
7
7
|
'/data': 'Browse all data loaded into the server',
|
|
8
8
|
'/dependency': 'Dependency data',
|
|
9
|
+
'/diff': 'Diff operations',
|
|
9
10
|
'/dump': 'Dump operations',
|
|
10
11
|
'/query': 'List of available queries',
|
|
11
12
|
'/task': 'List of available tasks',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/http/routes/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/http/routes/index.ts"],"names":[],"mappings":"AAoCA,QAAA,MAAM,MAAM,4CAAW,CAAC;AAqCxB,eAAe,MAAM,CAAC"}
|
|
@@ -13,6 +13,7 @@ const dependency_1 = require("./dependency");
|
|
|
13
13
|
const indexUrl_1 = require("./indexUrl");
|
|
14
14
|
const indexUUID_1 = require("./indexUUID");
|
|
15
15
|
const subset_1 = require("./subset");
|
|
16
|
+
const diff_1 = require("./diff");
|
|
16
17
|
const routes = (0, express_1.Router)();
|
|
17
18
|
routes.get('/', home_1.home);
|
|
18
19
|
routes.get('/docs', docs_1.docs);
|
|
@@ -28,6 +29,10 @@ routes.get('/task', task_1.taskIndex);
|
|
|
28
29
|
routes.get('/task/:taskId', task_1.runTask);
|
|
29
30
|
routes.get('/cache', cache_1.cacheIndex);
|
|
30
31
|
routes.get('/cache/:cacheBinId/clear', cache_1.cacheClear);
|
|
32
|
+
routes.get('/diff', diff_1.diffIndex);
|
|
33
|
+
routes.get('/diff/incremental', diff_1.diffIncremental);
|
|
34
|
+
routes.get('/diff/full', diff_1.diffFull);
|
|
35
|
+
routes.get('/diff/reset', diff_1.diffReset);
|
|
31
36
|
routes.get('/dump', dump_1.dumpIndex);
|
|
32
37
|
routes.get('/dump/incremental', dump_1.dumpIncremental);
|
|
33
38
|
routes.get('/dump/full', dump_1.dumpFull);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
extends includes/layout.pug
|
|
2
|
+
|
|
3
|
+
block vars
|
|
4
|
+
- var title = "Diff | Static Suite Data Server"
|
|
5
|
+
|
|
6
|
+
block content
|
|
7
|
+
h1(class="title is-1")="Diff"
|
|
8
|
+
table(class="table is-fullwidth is-hoverable")
|
|
9
|
+
tbody
|
|
10
|
+
each description, link in links
|
|
11
|
+
tr
|
|
12
|
+
td
|
|
13
|
+
a(href=link)= link
|
|
14
|
+
td=description
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataServer.d.ts","sourceRoot":"","sources":["../../src/lib/dataServer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AAKhE,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAG5C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EACL,WAAW,EACX,uBAAuB,EACvB,kBAAkB,EAClB,SAAS,EACT,WAAW,EACX,WAAW,EACZ,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,OAAO,EACP,gBAAgB,EAChB,qBAAqB,EACtB,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"dataServer.d.ts","sourceRoot":"","sources":["../../src/lib/dataServer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AAKhE,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAG5C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EACL,WAAW,EACX,uBAAuB,EACvB,kBAAkB,EAClB,SAAS,EACT,WAAW,EACX,WAAW,EACZ,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,OAAO,EACP,gBAAgB,EAChB,qBAAqB,EACtB,MAAM,oBAAoB,CAAC;AAG5B;;;;GAIG;AACH,QAAA,MAAM,UAAU;IACd;;;;;;OAMG;oBACa,qBAAqB,KAAG,gBAAgB;CA4CzD,CAAC;AACF,OAAO,EACL,UAAU,EACV,qBAAqB,EACrB,gBAAgB,EAChB,OAAO,EACP,QAAQ,EACR,OAAO,EACP,KAAK,EACL,WAAW,EACX,uBAAuB,EACvB,kBAAkB,EAClB,SAAS,EACT,WAAW,EACX,UAAU,EACV,WAAW,GACZ,CAAC"}
|
package/dist/lib/dataServer.js
CHANGED
|
@@ -14,6 +14,7 @@ const query_types_1 = require("./query/query.types");
|
|
|
14
14
|
Object.defineProperty(exports, "CacheStatus", { enumerable: true, get: function () { return query_types_1.CacheStatus; } });
|
|
15
15
|
const dataServer_types_1 = require("./dataServer.types");
|
|
16
16
|
Object.defineProperty(exports, "RunMode", { enumerable: true, get: function () { return dataServer_types_1.RunMode; } });
|
|
17
|
+
const dumpIndexHelper_1 = require("./store/dump/dumpIndexHelper");
|
|
17
18
|
/**
|
|
18
19
|
* The Data Server instance.
|
|
19
20
|
*
|
|
@@ -28,6 +29,7 @@ const dataServer = {
|
|
|
28
29
|
* @returns An object with the data store and the queryRunner service.
|
|
29
30
|
*/
|
|
30
31
|
init: (options) => {
|
|
32
|
+
const startDate = Date.now();
|
|
31
33
|
// Configure logger.
|
|
32
34
|
(0, logger_1.configureLogger)(options.logLevel, options.logFile);
|
|
33
35
|
// Configure data server.
|
|
@@ -46,6 +48,15 @@ const dataServer = {
|
|
|
46
48
|
}
|
|
47
49
|
// Load data from dataDir.
|
|
48
50
|
dataDir_1.dataDirManager.load();
|
|
51
|
+
// Create and load dump index.
|
|
52
|
+
if (config.dumpDir) {
|
|
53
|
+
if (dumpIndexHelper_1.dumpIndexHelper.isDumpIndexStale() ||
|
|
54
|
+
!dumpIndexHelper_1.dumpIndexHelper.isDumpIndexPresent()) {
|
|
55
|
+
dumpIndexHelper_1.dumpIndexHelper.createDumpIndex();
|
|
56
|
+
}
|
|
57
|
+
dumpIndexHelper_1.dumpIndexHelper.loadDumpIndex();
|
|
58
|
+
}
|
|
59
|
+
logger_1.logger.info(`Data Server loaded in ${Date.now() - startDate}ms.`);
|
|
49
60
|
return {
|
|
50
61
|
store: store_1.store,
|
|
51
62
|
queryRunner: query_1.queryRunner,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diff.types.d.ts","sourceRoot":"","sources":["../../../../src/lib/store/diff/diff.types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB;;;;OAIG;IACH,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAE9B;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,OAAO,CAAC,EAAE;QAAE,WAAW,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;CACnD,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,IAAI,GAAG;IACjB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"diff.types.d.ts","sourceRoot":"","sources":["../../../../src/lib/store/diff/diff.types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB;;;;OAIG;IACH,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAE9B;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,OAAO,CAAC,EAAE;QAAE,WAAW,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;CACnD,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,IAAI,GAAG;IACjB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAErB;;OAEG;IACH,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACtB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diffManager.d.ts","sourceRoot":"","sources":["../../../../src/lib/store/diff/diffManager.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAQ,MAAM,cAAc,CAAC;AAQjD,eAAO,MAAM,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"diffManager.d.ts","sourceRoot":"","sources":["../../../../src/lib/store/diff/diffManager.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAQ,MAAM,cAAc,CAAC;AAQjD,eAAO,MAAM,WAAW,EAAE,WAwEzB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dump.types.d.ts","sourceRoot":"","sources":["../../../../src/lib/store/dump/dump.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAE1C;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB;;;;;;;;;;;OAWG;IACH,IAAI,CAAC,OAAO,CAAC,EAAE;QAAE,WAAW,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IAE/C;;;;;;;OAOG;IACH,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,IAAI,GAAG;IACjB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;;;OAIG;IACH,OAAO,EAAE,GAAG,CACV,MAAM,EACN;QAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAC7D,CAAC;IAEF;;;;;OAKG;IACH,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,YAAY,EAAE,IAAI,CAAA;KAAE,CAAC,CAAC;IAE1E;;OAEG;IACH,IAAI,EAAE,IAAI,CAAC;CACZ,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,IAAI,EAAE,CAAC;CACf,CAAC"}
|
|
1
|
+
{"version":3,"file":"dump.types.d.ts","sourceRoot":"","sources":["../../../../src/lib/store/dump/dump.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAE1C;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB;;;;;;;;;;;OAWG;IACH,IAAI,CAAC,OAAO,CAAC,EAAE;QAAE,WAAW,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IAE/C;;;;;;;OAOG;IACH,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,IAAI,GAAG;IACjB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;;;OAIG;IACH,OAAO,EAAE,GAAG,CACV,MAAM,EACN;QAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAC7D,CAAC;IAEF;;;;;OAKG;IACH,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,YAAY,EAAE,IAAI,CAAA;KAAE,CAAC,CAAC;IAE1E;;OAEG;IACH,IAAI,EAAE,IAAI,CAAC;CACZ,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,IAAI,EAAE,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACpB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { IndexEntry } from './dump.types';
|
|
2
|
+
export declare const dumpIndexHelper: {
|
|
3
|
+
isDumpIndexStale: () => boolean;
|
|
4
|
+
isDumpIndexPresent: () => boolean;
|
|
5
|
+
saveDumpIndex: () => void;
|
|
6
|
+
createDumpIndex: () => void;
|
|
7
|
+
loadDumpIndex: () => void;
|
|
8
|
+
hasEntry: (relativeFilePath: string) => boolean;
|
|
9
|
+
getEntry: (relativeFilePath: string) => IndexEntry | undefined;
|
|
10
|
+
addEntry: (relativeFilePath: string, entry: IndexEntry) => void;
|
|
11
|
+
removeEntry: (relativeFilePath: string) => void;
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=dumpIndexHelper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dumpIndexHelper.d.ts","sourceRoot":"","sources":["../../../../src/lib/store/dump/dumpIndexHelper.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAiC1C,eAAO,MAAM,eAAe;4BACJ,OAAO;8BAYL,OAAO;yBAEZ,IAAI;2BASF,IAAI;yBAgCN,IAAI;iCAqBM,MAAM,KAAG,OAAO;iCAEhB,MAAM,KAAG,UAAU,GAAG,SAAS;iCAG/B,MAAM,SAAS,UAAU,KAAG,IAAI;oCAK7B,MAAM,KAAG,IAAI;CAI9C,CAAC"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.dumpIndexHelper = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const logger_1 = require("../../utils/logger");
|
|
9
|
+
const string_1 = require("../../utils/string");
|
|
10
|
+
const config_1 = require("../../config");
|
|
11
|
+
// import { Dump, DumpMetadata } from './dump.types';
|
|
12
|
+
// import { unixEpochUniqueId } from '../workDir';
|
|
13
|
+
const fs_2 = require("../../utils/fs");
|
|
14
|
+
const index = new Map();
|
|
15
|
+
let isStale = undefined;
|
|
16
|
+
const getIndexFilepath = () => `${config_1.config.dumpDir}/files.idx`;
|
|
17
|
+
const getIndexIsStaleFlagFilepath = () => `${config_1.config.dumpDir}/index-is-stale.flag`;
|
|
18
|
+
const indexToString = () => {
|
|
19
|
+
const indexLines = [];
|
|
20
|
+
index.forEach((value, filePath) => {
|
|
21
|
+
const line = [filePath, value.hash, value.url];
|
|
22
|
+
indexLines.push(line.join('\t'));
|
|
23
|
+
});
|
|
24
|
+
return indexLines.join('\n');
|
|
25
|
+
};
|
|
26
|
+
const setIsStale = (value) => {
|
|
27
|
+
if (isStale !== value) {
|
|
28
|
+
isStale = value;
|
|
29
|
+
const indexIsStaleFlagFilepath = getIndexIsStaleFlagFilepath();
|
|
30
|
+
if (isStale === true) {
|
|
31
|
+
fs_1.default.writeFileSync(indexIsStaleFlagFilepath, '');
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
if (fs_1.default.existsSync(indexIsStaleFlagFilepath)) {
|
|
35
|
+
fs_1.default.unlinkSync(indexIsStaleFlagFilepath);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
exports.dumpIndexHelper = {
|
|
41
|
+
isDumpIndexStale: () => {
|
|
42
|
+
if (isStale === undefined) {
|
|
43
|
+
const indexIsStaleFlagFilepath = getIndexIsStaleFlagFilepath();
|
|
44
|
+
if (fs_1.default.existsSync(indexIsStaleFlagFilepath)) {
|
|
45
|
+
setIsStale(true);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
setIsStale(false);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return !!isStale;
|
|
52
|
+
},
|
|
53
|
+
isDumpIndexPresent: () => fs_1.default.existsSync(getIndexFilepath()),
|
|
54
|
+
saveDumpIndex: () => {
|
|
55
|
+
if (isStale) {
|
|
56
|
+
const indexFilepath = getIndexFilepath();
|
|
57
|
+
const indexAsString = indexToString().trim();
|
|
58
|
+
fs_1.default.writeFileSync(indexFilepath, indexAsString);
|
|
59
|
+
setIsStale(false);
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
createDumpIndex: () => {
|
|
63
|
+
if (config_1.config.dumpDir) {
|
|
64
|
+
setIsStale(true);
|
|
65
|
+
logger_1.logger.info('Creating dump index...');
|
|
66
|
+
const startDate = Date.now();
|
|
67
|
+
index.clear();
|
|
68
|
+
const filesDumpDir = `${config_1.config.dumpDir}/files`;
|
|
69
|
+
const relativeFilePaths = (0, fs_2.findFilesInDir)(filesDumpDir);
|
|
70
|
+
relativeFilePaths.forEach(relativeFilePath => {
|
|
71
|
+
const fileContent = (0, fs_2.getFileContent)(`${filesDumpDir}/${relativeFilePath}`);
|
|
72
|
+
if (fileContent.raw) {
|
|
73
|
+
const url = fileContent.json
|
|
74
|
+
? fileContent.json.data?.content?.url?.path
|
|
75
|
+
: null;
|
|
76
|
+
const hash = (0, string_1.createHash)(fileContent.raw);
|
|
77
|
+
index.set(relativeFilePath, { hash, url });
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
// Save index into disk
|
|
81
|
+
exports.dumpIndexHelper.saveDumpIndex();
|
|
82
|
+
logger_1.logger.info(`${relativeFilePaths.length} files in dump indexed in ${Date.now() - startDate}ms.`);
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
loadDumpIndex: () => {
|
|
86
|
+
if (config_1.config.dumpDir) {
|
|
87
|
+
logger_1.logger.info('Loading dump index...');
|
|
88
|
+
const startDate = Date.now();
|
|
89
|
+
const indexFilepath = getIndexFilepath();
|
|
90
|
+
const data = fs_1.default.readFileSync(indexFilepath).toString().trim();
|
|
91
|
+
index.clear();
|
|
92
|
+
// Split lines and remove empty ones.
|
|
93
|
+
const dataLines = data.split('\n').filter(line => !!line);
|
|
94
|
+
dataLines.forEach(line => {
|
|
95
|
+
const [relativeFilePath, hash, url] = line.split('\t');
|
|
96
|
+
index.set(relativeFilePath, { hash, url });
|
|
97
|
+
});
|
|
98
|
+
logger_1.logger.info(`${dataLines.length} entries loaded from dump index in ${Date.now() - startDate}ms.`);
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
hasEntry: (relativeFilePath) => index.has(relativeFilePath),
|
|
102
|
+
getEntry: (relativeFilePath) => index.get(relativeFilePath),
|
|
103
|
+
addEntry: (relativeFilePath, entry) => {
|
|
104
|
+
setIsStale(true);
|
|
105
|
+
index.set(relativeFilePath, entry);
|
|
106
|
+
},
|
|
107
|
+
removeEntry: (relativeFilePath) => {
|
|
108
|
+
setIsStale(true);
|
|
109
|
+
index.delete(relativeFilePath);
|
|
110
|
+
},
|
|
111
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dumpManager.d.ts","sourceRoot":"","sources":["../../../../src/lib/store/dump/dumpManager.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dumpManager.d.ts","sourceRoot":"","sources":["../../../../src/lib/store/dump/dumpManager.ts"],"names":[],"mappings":"AASA,OAAO,EAAQ,WAAW,EAAE,MAAM,cAAc,CAAC;AA6GjD,eAAO,MAAM,WAAW,EAAE,WA4EzB,CAAC"}
|
|
@@ -14,59 +14,49 @@ const store_1 = require("../store");
|
|
|
14
14
|
const diffManager_1 = require("../diff/diffManager");
|
|
15
15
|
const hook_1 = require("../hook");
|
|
16
16
|
const dumpMetadataHelper_1 = require("./dumpMetadataHelper");
|
|
17
|
-
const
|
|
17
|
+
const dumpIndexHelper_1 = require("./dumpIndexHelper");
|
|
18
|
+
const string_1 = require("../../utils/string");
|
|
19
|
+
const storeUpdatedFiles = (diff, dump, filesDumpDir) => {
|
|
18
20
|
diff.updated.forEach(relativeFilepath => {
|
|
19
21
|
const storeFileContentData = store_1.store.data.get(relativeFilepath);
|
|
20
22
|
if (storeFileContentData) {
|
|
21
|
-
const absoluteFilepathInDumpDir = `${
|
|
23
|
+
const absoluteFilepathInDumpDir = `${filesDumpDir}/${relativeFilepath}`;
|
|
22
24
|
try {
|
|
23
|
-
// Create parent directories if they are missing.
|
|
24
|
-
const dir = path_1.default.dirname(absoluteFilepathInDumpDir);
|
|
25
|
-
if (!fs_1.default.existsSync(dir)) {
|
|
26
|
-
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
27
|
-
}
|
|
28
25
|
// If store data is an object, stringify it to execute its
|
|
29
26
|
// queries and resolve its includes.
|
|
30
27
|
const isJson = (0, fs_2.isJsonFile)(relativeFilepath);
|
|
31
28
|
const storeFileContentString = isJson
|
|
32
29
|
? JSON.stringify(storeFileContentData)
|
|
33
30
|
: storeFileContentData;
|
|
34
|
-
// Before overwriting a file, check it has changed.
|
|
31
|
+
// Before overwriting a file, check if it has changed.
|
|
35
32
|
let needsSave = true;
|
|
36
33
|
let oldPublicUrl = null;
|
|
37
34
|
const newPublicUrl = storeFileContentData.data?.content?.url?.path || null;
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
const newHash = (0, string_1.createHash)(storeFileContentString);
|
|
36
|
+
const indexEntry = dumpIndexHelper_1.dumpIndexHelper.getEntry(relativeFilepath);
|
|
37
|
+
if (indexEntry) {
|
|
38
|
+
if (newHash === indexEntry.hash) {
|
|
41
39
|
// No need to save it, file has not changed.
|
|
42
40
|
needsSave = false;
|
|
43
41
|
}
|
|
44
|
-
else if (isJson
|
|
45
|
-
// Get old public URL before it changes on disk.
|
|
46
|
-
oldPublicUrl =
|
|
47
|
-
JSON.parse(dumpFileContentString)?.data?.content?.url?.path ||
|
|
48
|
-
null;
|
|
49
|
-
/*
|
|
50
|
-
// Save a copy for later reference.
|
|
51
|
-
const backupAbsoluteFilepathInDumpDir =
|
|
52
|
-
absoluteFilepathInDumpDir.replace(
|
|
53
|
-
'/dump/files/',
|
|
54
|
-
'/dump/files.bak/',
|
|
55
|
-
);
|
|
56
|
-
const backupDir = path.dirname(backupAbsoluteFilepathInDumpDir);
|
|
57
|
-
if (!fs.existsSync(backupDir)) {
|
|
58
|
-
fs.mkdirSync(backupDir, { recursive: true });
|
|
59
|
-
}
|
|
60
|
-
fs.renameSync(
|
|
61
|
-
absoluteFilepathInDumpDir,
|
|
62
|
-
backupAbsoluteFilepathInDumpDir,
|
|
63
|
-
);
|
|
64
|
-
*/
|
|
42
|
+
else if (isJson) {
|
|
43
|
+
// Get old public URL before it changes on disk and index.
|
|
44
|
+
oldPublicUrl = indexEntry.url;
|
|
65
45
|
}
|
|
66
46
|
}
|
|
67
47
|
if (needsSave) {
|
|
68
|
-
//
|
|
48
|
+
// Create parent directories if they are missing.
|
|
49
|
+
const dir = path_1.default.dirname(absoluteFilepathInDumpDir);
|
|
50
|
+
if (!fs_1.default.existsSync(dir)) {
|
|
51
|
+
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
52
|
+
}
|
|
53
|
+
// Save it on disk.
|
|
69
54
|
fs_1.default.writeFileSync(absoluteFilepathInDumpDir, storeFileContentString);
|
|
55
|
+
// Save it to index.
|
|
56
|
+
dumpIndexHelper_1.dumpIndexHelper.addEntry(relativeFilepath, {
|
|
57
|
+
hash: newHash,
|
|
58
|
+
url: newPublicUrl,
|
|
59
|
+
});
|
|
70
60
|
// Mark it as updated.
|
|
71
61
|
dump.updated.set(relativeFilepath, {
|
|
72
62
|
oldPublicUrl,
|
|
@@ -83,18 +73,20 @@ const storeUpdatedFiles = (diff, dump, dumpDir) => {
|
|
|
83
73
|
}
|
|
84
74
|
});
|
|
85
75
|
};
|
|
86
|
-
const removeDeletedFiles = (diff, dump,
|
|
76
|
+
const removeDeletedFiles = (diff, dump, filesDumpDir) => {
|
|
87
77
|
diff.deleted.forEach(relativeFilepath => {
|
|
88
|
-
const absoluteFilepath = `${
|
|
78
|
+
const absoluteFilepath = `${filesDumpDir}/${relativeFilepath}`;
|
|
89
79
|
try {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const oldPublicUrl =
|
|
80
|
+
const indexEntry = dumpIndexHelper_1.dumpIndexHelper.getEntry(relativeFilepath);
|
|
81
|
+
if (indexEntry) {
|
|
82
|
+
// Get old public URLs before they change on disk and index.
|
|
83
|
+
const oldPublicUrl = indexEntry.url;
|
|
94
84
|
// Delete it.
|
|
95
85
|
fs_1.default.unlinkSync(absoluteFilepath);
|
|
96
86
|
// Delete any empty directory.
|
|
97
87
|
(0, fs_2.removeEmptyDirsUpwards)(path_1.default.dirname(absoluteFilepath));
|
|
88
|
+
// Delete it from index.
|
|
89
|
+
dumpIndexHelper_1.dumpIndexHelper.removeEntry(relativeFilepath);
|
|
98
90
|
// Mark it as deleted.
|
|
99
91
|
dump.deleted.set(relativeFilepath, {
|
|
100
92
|
oldPublicUrl,
|
|
@@ -121,12 +113,15 @@ exports.dumpManager = {
|
|
|
121
113
|
diff,
|
|
122
114
|
};
|
|
123
115
|
if (config_1.config.dumpDir) {
|
|
124
|
-
const
|
|
116
|
+
const filesDumpDir = `${config_1.config.dumpDir}/files`;
|
|
125
117
|
if (diff.updated.size || diff.deleted.size) {
|
|
118
|
+
dumpMetadataHelper_1.dumpMetadataHelper.storeDumpMetadata(dump);
|
|
126
119
|
// Store updated files.
|
|
127
|
-
storeUpdatedFiles(diff, dump,
|
|
120
|
+
storeUpdatedFiles(diff, dump, filesDumpDir);
|
|
128
121
|
// Remove deleted files.
|
|
129
|
-
removeDeletedFiles(diff, dump,
|
|
122
|
+
removeDeletedFiles(diff, dump, filesDumpDir);
|
|
123
|
+
// Save dump index
|
|
124
|
+
dumpIndexHelper_1.dumpIndexHelper.saveDumpIndex();
|
|
130
125
|
// Invoke "onDumpCreate" hook.
|
|
131
126
|
dump = hook_1.hookManager.invokeOnDumpCreate(dump);
|
|
132
127
|
const execTimeMs = (microtime_1.default.now() - startDate) / 1000;
|
|
@@ -140,12 +135,6 @@ exports.dumpManager = {
|
|
|
140
135
|
diffManager_1.diffManager.reset(diff.toUniqueId);
|
|
141
136
|
}
|
|
142
137
|
logger_1.logger.info(`Dump created in ${execTimeMs} ms. Updated: ${dump.updated.size} / Deleted: ${dump.deleted.size}`);
|
|
143
|
-
/*
|
|
144
|
-
// Log dump if not empty
|
|
145
|
-
if (dump.updated.size || dump.deleted.size) {
|
|
146
|
-
logger.debug(`Dump: "${JSON.stringify(jsonify(dump))}"`);
|
|
147
|
-
}
|
|
148
|
-
*/
|
|
149
138
|
}
|
|
150
139
|
else {
|
|
151
140
|
// Resetting the diff must happen when no other operations are pending.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dumpMetadataHelper.d.ts","sourceRoot":"","sources":["../../../../src/lib/store/dump/dumpMetadataHelper.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAKlD,eAAO,MAAM,kBAAkB;8BACH,IAAI,KAAG,OAAO;sCA6BN,MAAM,GAAG,YAAY;8BAuB7B,MAAM;
|
|
1
|
+
{"version":3,"file":"dumpMetadataHelper.d.ts","sourceRoot":"","sources":["../../../../src/lib/store/dump/dumpMetadataHelper.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAKlD,eAAO,MAAM,kBAAkB;8BACH,IAAI,KAAG,OAAO;sCA6BN,MAAM,GAAG,YAAY;8BAuB7B,MAAM;CAYjC,CAAC"}
|
|
@@ -17,7 +17,7 @@ exports.dumpMetadataHelper = {
|
|
|
17
17
|
current: workDir_1.unixEpochUniqueId,
|
|
18
18
|
dumps: [],
|
|
19
19
|
};
|
|
20
|
-
let currentDumpMetadata
|
|
20
|
+
let currentDumpMetadata;
|
|
21
21
|
try {
|
|
22
22
|
currentDumpMetadata = JSON.parse(fs_1.default.readFileSync(metadataFilepath).toString());
|
|
23
23
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
@@ -54,6 +54,7 @@ exports.dumpMetadataHelper = {
|
|
|
54
54
|
},
|
|
55
55
|
getCurrentDumpUniqueId() {
|
|
56
56
|
const metadataFilepath = getMetadataFilepath();
|
|
57
|
+
logger_1.logger.debug(`metadataFilepath: ${metadataFilepath}`);
|
|
57
58
|
const metadata = JSON.parse(fs_1.default.existsSync(metadataFilepath)
|
|
58
59
|
? fs_1.default.readFileSync(metadataFilepath).toString()
|
|
59
60
|
: '[]');
|
|
@@ -28,7 +28,7 @@ exports.isJsonFile = isJsonFile;
|
|
|
28
28
|
* @returns The file contents as a string if file is found, or null otherwise.
|
|
29
29
|
*/
|
|
30
30
|
const readFile = (filePath) => {
|
|
31
|
-
let content
|
|
31
|
+
let content;
|
|
32
32
|
try {
|
|
33
33
|
content = fs_1.default.readFileSync(filePath, { encoding: 'utf8', flag: 'r' });
|
|
34
34
|
}
|
|
@@ -48,4 +48,10 @@ export declare const parseUniqueId: (uniqueId: string) => Date | null;
|
|
|
48
48
|
* @param uniqueId - A unique id to be checked
|
|
49
49
|
*/
|
|
50
50
|
export declare const isUniqueId: (uniqueId: string) => boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Creates a hash from a string
|
|
53
|
+
*
|
|
54
|
+
* @param data - A string of data
|
|
55
|
+
*/
|
|
56
|
+
export declare const createHash: (data: string) => string;
|
|
51
57
|
//# sourceMappingURL=stringUtils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stringUtils.d.ts","sourceRoot":"","sources":["../../../../src/lib/utils/string/stringUtils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAEvD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAEtC;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,GAAI,YAAY,MAAM,KAAG,GAQpD,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,oBAAoB,GAC/B,aAAa,MAAM,KAClB,qBAWF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,GAAI,UAAU,MAAM,KAAG,IAAI,GAAG,IAevD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,UAAU,GAAI,UAAU,MAAM,KAAG,OAC+B,CAAC"}
|
|
1
|
+
{"version":3,"file":"stringUtils.d.ts","sourceRoot":"","sources":["../../../../src/lib/utils/string/stringUtils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAEvD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAEtC;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,GAAI,YAAY,MAAM,KAAG,GAQpD,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,oBAAoB,GAC/B,aAAa,MAAM,KAClB,qBAWF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,GAAI,UAAU,MAAM,KAAG,IAAI,GAAG,IAevD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,UAAU,GAAI,UAAU,MAAM,KAAG,OAC+B,CAAC;AAE9E;;;;GAIG;AACH,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,KAAG,MAC0B,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isUniqueId = exports.parseUniqueId = exports.parseURLSearchParams = exports.parseJsonString = exports.VARIANT_SEPARATOR = void 0;
|
|
3
|
+
exports.createHash = exports.isUniqueId = exports.parseUniqueId = exports.parseURLSearchParams = exports.parseJsonString = exports.VARIANT_SEPARATOR = void 0;
|
|
4
4
|
const logger_1 = require("../logger");
|
|
5
5
|
/**
|
|
6
6
|
* Separator for variant data files saved to storage.
|
|
@@ -87,3 +87,10 @@ exports.parseUniqueId = parseUniqueId;
|
|
|
87
87
|
*/
|
|
88
88
|
const isUniqueId = (uniqueId) => /(\d{4})-(\d{2})-(\d{2})_(\d{2})-(\d{2})-(\d{2})\.(\d{3}).*/.test(uniqueId);
|
|
89
89
|
exports.isUniqueId = isUniqueId;
|
|
90
|
+
/**
|
|
91
|
+
* Creates a hash from a string
|
|
92
|
+
*
|
|
93
|
+
* @param data - A string of data
|
|
94
|
+
*/
|
|
95
|
+
const createHash = (data) => require('crypto').createHash('sha1').update(data).digest('base64');
|
|
96
|
+
exports.createHash = createHash;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@static-suite/static-suite-data-server",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "A flexible, fast and developer friendly Data Server for Static Suite",
|
|
5
5
|
"main": "./dist/lib/index.js",
|
|
6
6
|
"typings": "./dist/lib/index.d.ts",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"decache": "^4.6.1",
|
|
22
22
|
"express": "^5.1.0",
|
|
23
23
|
"fast-glob": "^3.2.12",
|
|
24
|
-
"marked": "^
|
|
24
|
+
"marked": "^18.0.3",
|
|
25
25
|
"microtime": "^3.1.1",
|
|
26
26
|
"mime-types": "^3.0.1",
|
|
27
27
|
"pug": "^3.0.3",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"prepare": "husky"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@eslint/js": "^
|
|
51
|
+
"@eslint/js": "^10.0.1",
|
|
52
52
|
"@types/cors": "^2.8.13",
|
|
53
53
|
"@types/express": "^5.0.3",
|
|
54
54
|
"@types/jest": "^30.0.0",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"@types/yargs": "^17.0.22",
|
|
60
60
|
"@typescript-eslint/eslint-plugin": "^8.43.0",
|
|
61
61
|
"@typescript-eslint/parser": "^8.43.0",
|
|
62
|
-
"eslint": "^
|
|
62
|
+
"eslint": "^10.3.0",
|
|
63
63
|
"eslint-import-resolver-typescript": "^4.4.4",
|
|
64
64
|
"eslint-plugin-import": "^2.27.5",
|
|
65
65
|
"eslint-plugin-prettier": "^5.5.4",
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Request, Response } from 'express';
|
|
2
|
+
import { diffManager } from '../../lib/store/diff';
|
|
3
|
+
import { jsonify } from '../../lib/utils/object';
|
|
4
|
+
|
|
5
|
+
const diffIndex = (req: Request, res: Response): void => {
|
|
6
|
+
res.render('diffIndex', {
|
|
7
|
+
links: {
|
|
8
|
+
'/diff/incremental': 'Execute an incremental dump',
|
|
9
|
+
'/diff/full': 'Execute a full dump',
|
|
10
|
+
'/diff/reset':
|
|
11
|
+
'Clears intermediate changes tracked by dependency manager',
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const diffAction = (
|
|
17
|
+
req: Request,
|
|
18
|
+
res: Response,
|
|
19
|
+
incremental: boolean,
|
|
20
|
+
): void => {
|
|
21
|
+
const diff = diffManager.getDiff({ incremental });
|
|
22
|
+
const diffAsJson: any = jsonify(diff);
|
|
23
|
+
|
|
24
|
+
res.status(200);
|
|
25
|
+
res.set({ 'Content-Type': 'application/json' });
|
|
26
|
+
res.send(diffAsJson);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const diffIncremental = (req: Request, res: Response): void => {
|
|
30
|
+
diffAction(req, res, true);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const diffFull = (req: Request, res: Response): void => {
|
|
34
|
+
diffAction(req, res, false);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const diffReset = (req: Request, res: Response): void => {
|
|
38
|
+
const args: any = req.query;
|
|
39
|
+
if (args?.uniqueId) {
|
|
40
|
+
diffManager.reset(args.uniqueId);
|
|
41
|
+
}
|
|
42
|
+
res.status(200);
|
|
43
|
+
res.set({ 'Content-Type': 'application/json' });
|
|
44
|
+
res.send({ status: 'done' });
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export { diffIndex, diffIncremental, diffFull, diffReset };
|
package/src/http/routes/home.ts
CHANGED
|
@@ -5,6 +5,7 @@ export const home = (req: Request, res: Response): void => {
|
|
|
5
5
|
links: {
|
|
6
6
|
'/data': 'Browse all data loaded into the server',
|
|
7
7
|
'/dependency': 'Dependency data',
|
|
8
|
+
'/diff': 'Diff operations',
|
|
8
9
|
'/dump': 'Dump operations',
|
|
9
10
|
'/query': 'List of available queries',
|
|
10
11
|
'/task': 'List of available tasks',
|
package/src/http/routes/index.ts
CHANGED
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
import { indexUrl } from './indexUrl';
|
|
33
33
|
import { indexUUID } from './indexUUID';
|
|
34
34
|
import { subset } from './subset';
|
|
35
|
+
import { diffFull, diffIncremental, diffIndex, diffReset } from './diff';
|
|
35
36
|
|
|
36
37
|
const routes = Router();
|
|
37
38
|
|
|
@@ -49,6 +50,10 @@ routes.get('/task', taskIndex);
|
|
|
49
50
|
routes.get('/task/:taskId', runTask);
|
|
50
51
|
routes.get('/cache', cacheIndex);
|
|
51
52
|
routes.get('/cache/:cacheBinId/clear', cacheClear);
|
|
53
|
+
routes.get('/diff', diffIndex);
|
|
54
|
+
routes.get('/diff/incremental', diffIncremental);
|
|
55
|
+
routes.get('/diff/full', diffFull);
|
|
56
|
+
routes.get('/diff/reset', diffReset);
|
|
52
57
|
routes.get('/dump', dumpIndex);
|
|
53
58
|
routes.get('/dump/incremental', dumpIncremental);
|
|
54
59
|
routes.get('/dump/full', dumpFull);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Request, Response } from 'express';
|
|
2
|
-
import { StoreSubsetOptions } from 'lib/store/store.types';
|
|
2
|
+
import { StoreSubsetOptions } from '../../lib/store/store.types';
|
|
3
3
|
import { store } from '../../lib/store';
|
|
4
4
|
import { dataDirManager } from '../../lib/store/dataDir';
|
|
5
5
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
extends includes/layout.pug
|
|
2
|
+
|
|
3
|
+
block vars
|
|
4
|
+
- var title = "Diff | Static Suite Data Server"
|
|
5
|
+
|
|
6
|
+
block content
|
|
7
|
+
h1(class="title is-1")="Diff"
|
|
8
|
+
table(class="table is-fullwidth is-hoverable")
|
|
9
|
+
tbody
|
|
10
|
+
each description, link in links
|
|
11
|
+
tr
|
|
12
|
+
td
|
|
13
|
+
a(href=link)= link
|
|
14
|
+
td=description
|
package/src/lib/dataServer.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { configureLogger } from './utils/logger';
|
|
1
|
+
import { configureLogger, logger } from './utils/logger';
|
|
2
2
|
import { LogLevel, LogFile } from './utils/logger/logger.types';
|
|
3
3
|
import { initWatcher } from './watcher';
|
|
4
4
|
import { setConfig } from './config';
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
DataServerReturn,
|
|
22
22
|
DataServerInitOptions,
|
|
23
23
|
} from './dataServer.types';
|
|
24
|
+
import { dumpIndexHelper } from './store/dump/dumpIndexHelper';
|
|
24
25
|
|
|
25
26
|
/**
|
|
26
27
|
* The Data Server instance.
|
|
@@ -36,6 +37,8 @@ const dataServer = {
|
|
|
36
37
|
* @returns An object with the data store and the queryRunner service.
|
|
37
38
|
*/
|
|
38
39
|
init: (options: DataServerInitOptions): DataServerReturn => {
|
|
40
|
+
const startDate = Date.now();
|
|
41
|
+
|
|
39
42
|
// Configure logger.
|
|
40
43
|
configureLogger(options.logLevel, options.logFile);
|
|
41
44
|
|
|
@@ -58,6 +61,19 @@ const dataServer = {
|
|
|
58
61
|
// Load data from dataDir.
|
|
59
62
|
dataDirManager.load();
|
|
60
63
|
|
|
64
|
+
// Create and load dump index.
|
|
65
|
+
if (config.dumpDir) {
|
|
66
|
+
if (
|
|
67
|
+
dumpIndexHelper.isDumpIndexStale() ||
|
|
68
|
+
!dumpIndexHelper.isDumpIndexPresent()
|
|
69
|
+
) {
|
|
70
|
+
dumpIndexHelper.createDumpIndex();
|
|
71
|
+
}
|
|
72
|
+
dumpIndexHelper.loadDumpIndex();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
logger.info(`Data Server loaded in ${Date.now() - startDate}ms.`);
|
|
76
|
+
|
|
61
77
|
return {
|
|
62
78
|
store,
|
|
63
79
|
queryRunner,
|
|
@@ -27,6 +27,7 @@ export const diffManager: DiffManager = {
|
|
|
27
27
|
const currentDumpUniqueId = dumpMetadataHelper.getCurrentDumpUniqueId();
|
|
28
28
|
const isFirstDiffAfterReboot = lastDiffUniqueId === unixEpochUniqueId;
|
|
29
29
|
const isADumpAvailable = currentDumpUniqueId !== unixEpochUniqueId;
|
|
30
|
+
|
|
30
31
|
// If both checks passes, check if something has changed after last dump to avoid a full diff:
|
|
31
32
|
if (isFirstDiffAfterReboot && isADumpAvailable) {
|
|
32
33
|
const dataDirModificationUniqueId = changedFiles.toUniqueId;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import { logger } from '../../utils/logger';
|
|
3
|
+
import { createHash } from '../../utils/string';
|
|
4
|
+
import { config } from '../../config';
|
|
5
|
+
// import { Dump, DumpMetadata } from './dump.types';
|
|
6
|
+
// import { unixEpochUniqueId } from '../workDir';
|
|
7
|
+
import { findFilesInDir, getFileContent } from '../../utils/fs';
|
|
8
|
+
import { IndexEntry } from './dump.types';
|
|
9
|
+
|
|
10
|
+
const index = new Map<string, IndexEntry>();
|
|
11
|
+
|
|
12
|
+
let isStale: boolean | undefined = undefined;
|
|
13
|
+
|
|
14
|
+
const getIndexFilepath = () => `${config.dumpDir}/files.idx`;
|
|
15
|
+
const getIndexIsStaleFlagFilepath = () =>
|
|
16
|
+
`${config.dumpDir}/index-is-stale.flag`;
|
|
17
|
+
|
|
18
|
+
const indexToString = (): string => {
|
|
19
|
+
const indexLines: string[] = [];
|
|
20
|
+
index.forEach((value, filePath) => {
|
|
21
|
+
const line = [filePath, value.hash, value.url];
|
|
22
|
+
indexLines.push(line.join('\t'));
|
|
23
|
+
});
|
|
24
|
+
return indexLines.join('\n');
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const setIsStale = (value: boolean): void => {
|
|
28
|
+
if (isStale !== value) {
|
|
29
|
+
isStale = value;
|
|
30
|
+
const indexIsStaleFlagFilepath = getIndexIsStaleFlagFilepath();
|
|
31
|
+
if (isStale === true) {
|
|
32
|
+
fs.writeFileSync(indexIsStaleFlagFilepath, '');
|
|
33
|
+
} else {
|
|
34
|
+
if (fs.existsSync(indexIsStaleFlagFilepath)) {
|
|
35
|
+
fs.unlinkSync(indexIsStaleFlagFilepath);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const dumpIndexHelper = {
|
|
42
|
+
isDumpIndexStale: (): boolean => {
|
|
43
|
+
if (isStale === undefined) {
|
|
44
|
+
const indexIsStaleFlagFilepath = getIndexIsStaleFlagFilepath();
|
|
45
|
+
if (fs.existsSync(indexIsStaleFlagFilepath)) {
|
|
46
|
+
setIsStale(true);
|
|
47
|
+
} else {
|
|
48
|
+
setIsStale(false);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return !!isStale;
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
isDumpIndexPresent: (): boolean => fs.existsSync(getIndexFilepath()),
|
|
55
|
+
|
|
56
|
+
saveDumpIndex: (): void => {
|
|
57
|
+
if (isStale) {
|
|
58
|
+
const indexFilepath = getIndexFilepath();
|
|
59
|
+
const indexAsString = indexToString().trim();
|
|
60
|
+
fs.writeFileSync(indexFilepath, indexAsString);
|
|
61
|
+
setIsStale(false);
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
createDumpIndex: (): void => {
|
|
66
|
+
if (config.dumpDir) {
|
|
67
|
+
setIsStale(true);
|
|
68
|
+
logger.info('Creating dump index...');
|
|
69
|
+
const startDate = Date.now();
|
|
70
|
+
index.clear();
|
|
71
|
+
const filesDumpDir = `${config.dumpDir}/files`;
|
|
72
|
+
const relativeFilePaths = findFilesInDir(filesDumpDir);
|
|
73
|
+
relativeFilePaths.forEach(relativeFilePath => {
|
|
74
|
+
const fileContent = getFileContent(
|
|
75
|
+
`${filesDumpDir}/${relativeFilePath}`,
|
|
76
|
+
);
|
|
77
|
+
if (fileContent.raw) {
|
|
78
|
+
const url = fileContent.json
|
|
79
|
+
? fileContent.json.data?.content?.url?.path
|
|
80
|
+
: null;
|
|
81
|
+
const hash = createHash(fileContent.raw);
|
|
82
|
+
index.set(relativeFilePath, { hash, url });
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Save index into disk
|
|
87
|
+
dumpIndexHelper.saveDumpIndex();
|
|
88
|
+
|
|
89
|
+
logger.info(
|
|
90
|
+
`${relativeFilePaths.length} files in dump indexed in ${
|
|
91
|
+
Date.now() - startDate
|
|
92
|
+
}ms.`,
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
loadDumpIndex: (): void => {
|
|
98
|
+
if (config.dumpDir) {
|
|
99
|
+
logger.info('Loading dump index...');
|
|
100
|
+
const startDate = Date.now();
|
|
101
|
+
const indexFilepath = getIndexFilepath();
|
|
102
|
+
const data = fs.readFileSync(indexFilepath).toString().trim();
|
|
103
|
+
index.clear();
|
|
104
|
+
// Split lines and remove empty ones.
|
|
105
|
+
const dataLines: string[] = data.split('\n').filter(line => !!line);
|
|
106
|
+
dataLines.forEach(line => {
|
|
107
|
+
const [relativeFilePath, hash, url] = line.split('\t');
|
|
108
|
+
index.set(relativeFilePath, { hash, url });
|
|
109
|
+
});
|
|
110
|
+
logger.info(
|
|
111
|
+
`${dataLines.length} entries loaded from dump index in ${
|
|
112
|
+
Date.now() - startDate
|
|
113
|
+
}ms.`,
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
hasEntry: (relativeFilePath: string): boolean => index.has(relativeFilePath),
|
|
119
|
+
|
|
120
|
+
getEntry: (relativeFilePath: string): IndexEntry | undefined =>
|
|
121
|
+
index.get(relativeFilePath),
|
|
122
|
+
|
|
123
|
+
addEntry: (relativeFilePath: string, entry: IndexEntry): void => {
|
|
124
|
+
setIsStale(true);
|
|
125
|
+
index.set(relativeFilePath, entry);
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
removeEntry: (relativeFilePath: string): void => {
|
|
129
|
+
setIsStale(true);
|
|
130
|
+
index.delete(relativeFilePath);
|
|
131
|
+
},
|
|
132
|
+
};
|
|
@@ -2,12 +2,7 @@ import fs from 'fs';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import microtime from 'microtime';
|
|
4
4
|
import { logger } from '../../utils/logger';
|
|
5
|
-
import {
|
|
6
|
-
getFileContent,
|
|
7
|
-
isJsonFile,
|
|
8
|
-
readFile,
|
|
9
|
-
removeEmptyDirsUpwards,
|
|
10
|
-
} from '../../utils/fs';
|
|
5
|
+
import { isJsonFile, removeEmptyDirsUpwards } from '../../utils/fs';
|
|
11
6
|
import { config } from '../../config';
|
|
12
7
|
import { store } from '../store';
|
|
13
8
|
import { diffManager } from '../diff/diffManager';
|
|
@@ -15,19 +10,19 @@ import { Diff } from '../diff/diff.types';
|
|
|
15
10
|
import { Dump, DumpManager } from './dump.types';
|
|
16
11
|
import { hookManager } from '../hook';
|
|
17
12
|
import { dumpMetadataHelper } from './dumpMetadataHelper';
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
import { dumpIndexHelper } from './dumpIndexHelper';
|
|
14
|
+
import { createHash } from '../../utils/string';
|
|
15
|
+
|
|
16
|
+
const storeUpdatedFiles = (
|
|
17
|
+
diff: Diff,
|
|
18
|
+
dump: Dump,
|
|
19
|
+
filesDumpDir: string,
|
|
20
|
+
): void => {
|
|
20
21
|
diff.updated.forEach(relativeFilepath => {
|
|
21
22
|
const storeFileContentData = store.data.get(relativeFilepath);
|
|
22
23
|
if (storeFileContentData) {
|
|
23
|
-
const absoluteFilepathInDumpDir = `${
|
|
24
|
+
const absoluteFilepathInDumpDir = `${filesDumpDir}/${relativeFilepath}`;
|
|
24
25
|
try {
|
|
25
|
-
// Create parent directories if they are missing.
|
|
26
|
-
const dir = path.dirname(absoluteFilepathInDumpDir);
|
|
27
|
-
if (!fs.existsSync(dir)) {
|
|
28
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
29
|
-
}
|
|
30
|
-
|
|
31
26
|
// If store data is an object, stringify it to execute its
|
|
32
27
|
// queries and resolve its includes.
|
|
33
28
|
const isJson = isJsonFile(relativeFilepath);
|
|
@@ -35,43 +30,39 @@ const storeUpdatedFiles = (diff: Diff, dump: Dump, dumpDir: string): void => {
|
|
|
35
30
|
? JSON.stringify(storeFileContentData)
|
|
36
31
|
: storeFileContentData;
|
|
37
32
|
|
|
38
|
-
// Before overwriting a file, check it has changed.
|
|
33
|
+
// Before overwriting a file, check if it has changed.
|
|
39
34
|
let needsSave = true;
|
|
40
35
|
let oldPublicUrl: string | null = null;
|
|
41
36
|
const newPublicUrl: string | null =
|
|
42
37
|
storeFileContentData.data?.content?.url?.path || null;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
38
|
+
const newHash = createHash(storeFileContentString);
|
|
39
|
+
const indexEntry = dumpIndexHelper.getEntry(relativeFilepath);
|
|
40
|
+
if (indexEntry) {
|
|
41
|
+
if (newHash === indexEntry.hash) {
|
|
46
42
|
// No need to save it, file has not changed.
|
|
47
43
|
needsSave = false;
|
|
48
|
-
} else if (isJson
|
|
49
|
-
// Get old public URL before it changes on disk.
|
|
50
|
-
oldPublicUrl =
|
|
51
|
-
JSON.parse(dumpFileContentString)?.data?.content?.url?.path ||
|
|
52
|
-
null;
|
|
53
|
-
/*
|
|
54
|
-
// Save a copy for later reference.
|
|
55
|
-
const backupAbsoluteFilepathInDumpDir =
|
|
56
|
-
absoluteFilepathInDumpDir.replace(
|
|
57
|
-
'/dump/files/',
|
|
58
|
-
'/dump/files.bak/',
|
|
59
|
-
);
|
|
60
|
-
const backupDir = path.dirname(backupAbsoluteFilepathInDumpDir);
|
|
61
|
-
if (!fs.existsSync(backupDir)) {
|
|
62
|
-
fs.mkdirSync(backupDir, { recursive: true });
|
|
63
|
-
}
|
|
64
|
-
fs.renameSync(
|
|
65
|
-
absoluteFilepathInDumpDir,
|
|
66
|
-
backupAbsoluteFilepathInDumpDir,
|
|
67
|
-
);
|
|
68
|
-
*/
|
|
44
|
+
} else if (isJson) {
|
|
45
|
+
// Get old public URL before it changes on disk and index.
|
|
46
|
+
oldPublicUrl = indexEntry.url;
|
|
69
47
|
}
|
|
70
48
|
}
|
|
49
|
+
|
|
71
50
|
if (needsSave) {
|
|
72
|
-
//
|
|
51
|
+
// Create parent directories if they are missing.
|
|
52
|
+
const dir = path.dirname(absoluteFilepathInDumpDir);
|
|
53
|
+
if (!fs.existsSync(dir)) {
|
|
54
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Save it on disk.
|
|
73
58
|
fs.writeFileSync(absoluteFilepathInDumpDir, storeFileContentString);
|
|
74
59
|
|
|
60
|
+
// Save it to index.
|
|
61
|
+
dumpIndexHelper.addEntry(relativeFilepath, {
|
|
62
|
+
hash: newHash,
|
|
63
|
+
url: newPublicUrl,
|
|
64
|
+
});
|
|
65
|
+
|
|
75
66
|
// Mark it as updated.
|
|
76
67
|
dump.updated.set(relativeFilepath, {
|
|
77
68
|
oldPublicUrl,
|
|
@@ -91,15 +82,18 @@ const storeUpdatedFiles = (diff: Diff, dump: Dump, dumpDir: string): void => {
|
|
|
91
82
|
});
|
|
92
83
|
};
|
|
93
84
|
|
|
94
|
-
const removeDeletedFiles = (
|
|
85
|
+
const removeDeletedFiles = (
|
|
86
|
+
diff: Diff,
|
|
87
|
+
dump: Dump,
|
|
88
|
+
filesDumpDir: string,
|
|
89
|
+
): void => {
|
|
95
90
|
diff.deleted.forEach(relativeFilepath => {
|
|
96
|
-
const absoluteFilepath = `${
|
|
91
|
+
const absoluteFilepath = `${filesDumpDir}/${relativeFilepath}`;
|
|
97
92
|
try {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
const oldPublicUrl
|
|
102
|
-
dumpContent.json?.data?.content?.url?.path;
|
|
93
|
+
const indexEntry = dumpIndexHelper.getEntry(relativeFilepath);
|
|
94
|
+
if (indexEntry) {
|
|
95
|
+
// Get old public URLs before they change on disk and index.
|
|
96
|
+
const oldPublicUrl = indexEntry.url;
|
|
103
97
|
|
|
104
98
|
// Delete it.
|
|
105
99
|
fs.unlinkSync(absoluteFilepath);
|
|
@@ -107,6 +101,9 @@ const removeDeletedFiles = (diff: Diff, dump: Dump, dumpDir: string): void => {
|
|
|
107
101
|
// Delete any empty directory.
|
|
108
102
|
removeEmptyDirsUpwards(path.dirname(absoluteFilepath));
|
|
109
103
|
|
|
104
|
+
// Delete it from index.
|
|
105
|
+
dumpIndexHelper.removeEntry(relativeFilepath);
|
|
106
|
+
|
|
110
107
|
// Mark it as deleted.
|
|
111
108
|
dump.deleted.set(relativeFilepath, {
|
|
112
109
|
oldPublicUrl,
|
|
@@ -135,14 +132,19 @@ export const dumpManager: DumpManager = {
|
|
|
135
132
|
};
|
|
136
133
|
|
|
137
134
|
if (config.dumpDir) {
|
|
138
|
-
const
|
|
135
|
+
const filesDumpDir = `${config.dumpDir}/files`;
|
|
139
136
|
|
|
140
137
|
if (diff.updated.size || diff.deleted.size) {
|
|
138
|
+
dumpMetadataHelper.storeDumpMetadata(dump);
|
|
139
|
+
|
|
141
140
|
// Store updated files.
|
|
142
|
-
storeUpdatedFiles(diff, dump,
|
|
141
|
+
storeUpdatedFiles(diff, dump, filesDumpDir);
|
|
143
142
|
|
|
144
143
|
// Remove deleted files.
|
|
145
|
-
removeDeletedFiles(diff, dump,
|
|
144
|
+
removeDeletedFiles(diff, dump, filesDumpDir);
|
|
145
|
+
|
|
146
|
+
// Save dump index
|
|
147
|
+
dumpIndexHelper.saveDumpIndex();
|
|
146
148
|
|
|
147
149
|
// Invoke "onDumpCreate" hook.
|
|
148
150
|
dump = hookManager.invokeOnDumpCreate(dump);
|
|
@@ -162,13 +164,6 @@ export const dumpManager: DumpManager = {
|
|
|
162
164
|
logger.info(
|
|
163
165
|
`Dump created in ${execTimeMs} ms. Updated: ${dump.updated.size} / Deleted: ${dump.deleted.size}`,
|
|
164
166
|
);
|
|
165
|
-
|
|
166
|
-
/*
|
|
167
|
-
// Log dump if not empty
|
|
168
|
-
if (dump.updated.size || dump.deleted.size) {
|
|
169
|
-
logger.debug(`Dump: "${JSON.stringify(jsonify(dump))}"`);
|
|
170
|
-
}
|
|
171
|
-
*/
|
|
172
167
|
} else {
|
|
173
168
|
// Resetting the diff must happen when no other operations are pending.
|
|
174
169
|
diffManager.reset(diff.toUniqueId);
|
|
@@ -14,7 +14,7 @@ export const dumpMetadataHelper = {
|
|
|
14
14
|
current: unixEpochUniqueId,
|
|
15
15
|
dumps: [],
|
|
16
16
|
};
|
|
17
|
-
let currentDumpMetadata
|
|
17
|
+
let currentDumpMetadata;
|
|
18
18
|
try {
|
|
19
19
|
currentDumpMetadata = JSON.parse(
|
|
20
20
|
fs.readFileSync(metadataFilepath).toString(),
|
|
@@ -63,6 +63,7 @@ export const dumpMetadataHelper = {
|
|
|
63
63
|
getCurrentDumpUniqueId(): string {
|
|
64
64
|
const metadataFilepath = getMetadataFilepath();
|
|
65
65
|
|
|
66
|
+
logger.debug(`metadataFilepath: ${metadataFilepath}`);
|
|
66
67
|
const metadata = JSON.parse(
|
|
67
68
|
fs.existsSync(metadataFilepath)
|
|
68
69
|
? fs.readFileSync(metadataFilepath).toString()
|
|
@@ -25,7 +25,7 @@ export const isJsonFile = (filepath: string): boolean =>
|
|
|
25
25
|
* @returns The file contents as a string if file is found, or null otherwise.
|
|
26
26
|
*/
|
|
27
27
|
export const readFile = (filePath: string): string | null => {
|
|
28
|
-
let content
|
|
28
|
+
let content;
|
|
29
29
|
try {
|
|
30
30
|
content = fs.readFileSync(filePath, { encoding: 'utf8', flag: 'r' });
|
|
31
31
|
} catch (error) {
|
|
@@ -115,4 +115,3 @@ export const removeEmptyDirsUpwards = (dir: string): void => {
|
|
|
115
115
|
removeEmptyDirsUpwards(path.dirname(dir));
|
|
116
116
|
}
|
|
117
117
|
};
|
|
118
|
-
|
|
@@ -91,3 +91,11 @@ export const parseUniqueId = (uniqueId: string): Date | null => {
|
|
|
91
91
|
*/
|
|
92
92
|
export const isUniqueId = (uniqueId: string): boolean =>
|
|
93
93
|
/(\d{4})-(\d{2})-(\d{2})_(\d{2})-(\d{2})-(\d{2})\.(\d{3}).*/.test(uniqueId);
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Creates a hash from a string
|
|
97
|
+
*
|
|
98
|
+
* @param data - A string of data
|
|
99
|
+
*/
|
|
100
|
+
export const createHash = (data: string): string =>
|
|
101
|
+
require('crypto').createHash('sha1').update(data).digest('base64');
|
package/tsconfig.json
CHANGED
|
@@ -30,9 +30,9 @@
|
|
|
30
30
|
|
|
31
31
|
/* Strict Type-Checking Options */
|
|
32
32
|
"strict": true /* Enable all strict type-checking options. */,
|
|
33
|
-
"paths": {
|
|
33
|
+
/* "paths": {
|
|
34
34
|
"*": ["./src/*"]
|
|
35
|
-
} /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'.
|
|
35
|
+
} */ /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
|
36
36
|
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
|
37
37
|
// "typeRoots": [], /* List of folders to include type definitions from. */
|
|
38
38
|
"types": [
|