@static-suite/static-suite-data-server 1.0.5 → 1.0.7

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.
@@ -6,8 +6,8 @@ const object_1 = require("../../lib/utils/object");
6
6
  const diffIndex = (req, res) => {
7
7
  res.render('diffIndex', {
8
8
  links: {
9
- '/diff/incremental': 'Execute an incremental dump',
10
- '/diff/full': 'Execute a full dump',
9
+ '/diff/incremental': 'Execute an incremental diff',
10
+ '/diff/full': 'Execute a full diff',
11
11
  '/diff/reset': 'Clears intermediate changes tracked by dependency manager',
12
12
  },
13
13
  });
@@ -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,IAclD,CAAC"}
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;AAG5C,eAAO,MAAM,IAAI,GAAI,KAAK,OAAO,EAAE,KAAK,QAAQ,KAAG,IAelD,CAAC"}
@@ -1,8 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.home = void 0;
4
+ const package_json_1 = require("../../../package.json");
4
5
  const home = (req, res) => {
5
6
  res.render('home', {
7
+ version: package_json_1.version,
6
8
  links: {
7
9
  '/data': 'Browse all data loaded into the server',
8
10
  '/dependency': 'Dependency data',
@@ -1 +1 @@
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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/http/routes/index.ts"],"names":[],"mappings":"AAmCA,QAAA,MAAM,MAAM,4CAAW,CAAC;AAoCxB,eAAe,MAAM,CAAC"}
@@ -21,7 +21,6 @@ routes.get('/status/basic', status_1.statusBasic);
21
21
  routes.get('/status/index/url', status_1.statusIndexUrl);
22
22
  routes.get('/status/index/uuid', status_1.statusIndexUuid);
23
23
  routes.get('/status/index/custom', status_1.statusIndexCustom);
24
- routes.get('/status/diff', status_1.statusDiff);
25
24
  routes.get('/status', status_1.statusIndex);
26
25
  routes.get('/query', query_1.queryIndex);
27
26
  routes.get('/query/*queryDefinition', query_1.runQuery);
@@ -4,6 +4,5 @@ declare const statusBasic: (req: Request, res: Response) => void;
4
4
  declare const statusIndexUrl: (req: Request, res: Response) => void;
5
5
  declare const statusIndexUuid: (req: Request, res: Response) => void;
6
6
  declare const statusIndexCustom: (req: Request, res: Response) => void;
7
- declare const statusDiff: (req: Request, res: Response) => void;
8
- export { statusIndex, statusBasic, statusIndexUrl, statusIndexUuid, statusIndexCustom, statusDiff, };
7
+ export { statusIndex, statusBasic, statusIndexUrl, statusIndexUuid, statusIndexCustom, };
9
8
  //# sourceMappingURL=status.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/http/routes/status.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAU5C,QAAA,MAAM,WAAW,GAAI,KAAK,OAAO,EAAE,KAAK,QAAQ,KAAG,IAWlD,CAAC;AAEF,QAAA,MAAM,WAAW,GAAI,KAAK,OAAO,EAAE,KAAK,QAAQ,KAAG,IAelD,CAAC;AAEF,QAAA,MAAM,cAAc,GAAI,KAAK,OAAO,EAAE,KAAK,QAAQ,KAAG,IAKrD,CAAC;AAEF,QAAA,MAAM,eAAe,GAAI,KAAK,OAAO,EAAE,KAAK,QAAQ,KAAG,IAStD,CAAC;AAEF,QAAA,MAAM,iBAAiB,GAAI,KAAK,OAAO,EAAE,KAAK,QAAQ,KAAG,IAKxD,CAAC;AAEF,QAAA,MAAM,UAAU,GAAI,KAAK,OAAO,EAAE,KAAK,QAAQ,KAAG,IAKjD,CAAC;AAEF,OAAO,EACL,WAAW,EACX,WAAW,EACX,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,UAAU,GACX,CAAC"}
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/http/routes/status.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAQ5C,QAAA,MAAM,WAAW,GAAI,KAAK,OAAO,EAAE,KAAK,QAAQ,KAAG,IAUlD,CAAC;AAEF,QAAA,MAAM,WAAW,GAAI,KAAK,OAAO,EAAE,KAAK,QAAQ,KAAG,IAelD,CAAC;AAEF,QAAA,MAAM,cAAc,GAAI,KAAK,OAAO,EAAE,KAAK,QAAQ,KAAG,IAKrD,CAAC;AAEF,QAAA,MAAM,eAAe,GAAI,KAAK,OAAO,EAAE,KAAK,QAAQ,KAAG,IAStD,CAAC;AAEF,QAAA,MAAM,iBAAiB,GAAI,KAAK,OAAO,EAAE,KAAK,QAAQ,KAAG,IAKxD,CAAC;AAEF,OAAO,EACL,WAAW,EACX,WAAW,EACX,cAAc,EACd,eAAe,EACf,iBAAiB,GAClB,CAAC"}
@@ -1,13 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.statusDiff = exports.statusIndexCustom = exports.statusIndexUuid = exports.statusIndexUrl = exports.statusBasic = exports.statusIndex = void 0;
3
+ exports.statusIndexCustom = exports.statusIndexUuid = exports.statusIndexUrl = exports.statusBasic = exports.statusIndex = void 0;
4
4
  const dataDir_1 = require("../../lib/store/dataDir");
5
5
  const query_1 = require("../../lib/query");
6
6
  const config_1 = require("../../lib/config");
7
7
  const cache_1 = require("../../lib/utils/cache");
8
8
  const store_1 = require("../../lib/store");
9
- const object_1 = require("../../lib/utils/object");
10
- const diffManager_1 = require("../../lib/store/diff/diffManager");
11
9
  const statusIndex = (req, res) => {
12
10
  res.render('statusIndex', {
13
11
  links: {
@@ -16,7 +14,6 @@ const statusIndex = (req, res) => {
16
14
  '/status/index/uuid': 'List of indexed UUIDs by language',
17
15
  '/status/index/include': 'List of indexed includes',
18
16
  '/status/index/custom': 'List of custom indexes',
19
- '/status/diff': 'Executes a diff operation',
20
17
  },
21
18
  });
22
19
  };
@@ -60,10 +57,3 @@ const statusIndexCustom = (req, res) => {
60
57
  res.send(response);
61
58
  };
62
59
  exports.statusIndexCustom = statusIndexCustom;
63
- const statusDiff = (req, res) => {
64
- const response = (0, object_1.jsonify)(diffManager_1.diffManager.getDiff());
65
- res.status(200);
66
- res.set({ 'Content-Type': 'application/json' });
67
- res.send(response);
68
- };
69
- exports.statusDiff = statusDiff;
@@ -5,7 +5,7 @@ block vars
5
5
 
6
6
  block content
7
7
  h1(class="title is-1")="Available cache bins"
8
- table(class="table is-fullwidth is-hoverable")
8
+ table(class="table is-fullwidth is-hoverable")
9
9
  tbody
10
10
  if cacheBins.length
11
11
  each cacheBin in cacheBins
@@ -4,7 +4,7 @@ block vars
4
4
  - var title = "Static Suite Data Server"
5
5
 
6
6
  block content
7
- h1(class="title is-1")="Static Suite Data Server"
7
+ h1(class="title is-1")=`Static Suite Data Server ${version}`
8
8
  h2(class="subtitle")="Table of Contents"
9
9
  table(class="table is-fullwidth is-hoverable")
10
10
  tbody
@@ -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;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"}
1
+ {"version":3,"file":"dataServer.d.ts","sourceRoot":"","sources":["../../src/lib/dataServer.ts"],"names":[],"mappings":"AAEA,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;CA8CzD,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"}
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CacheStatus = exports.LogLevel = exports.RunMode = exports.dataServer = void 0;
4
+ const package_json_1 = require("../../package.json");
4
5
  const logger_1 = require("./utils/logger");
5
6
  const logger_types_1 = require("./utils/logger/logger.types");
6
7
  Object.defineProperty(exports, "LogLevel", { enumerable: true, get: function () { return logger_types_1.LogLevel; } });
@@ -56,7 +57,7 @@ const dataServer = {
56
57
  }
57
58
  dumpIndexHelper_1.dumpIndexHelper.loadDumpIndex();
58
59
  }
59
- logger_1.logger.info(`Data Server loaded in ${Date.now() - startDate}ms.`);
60
+ logger_1.logger.info(`Data Server ${package_json_1.version} loaded in ${Date.now() - startDate}ms.`);
60
61
  return {
61
62
  store: store_1.store,
62
63
  queryRunner: query_1.queryRunner,
@@ -7,6 +7,7 @@ export declare const dumpIndexHelper: {
7
7
  loadDumpIndex: () => void;
8
8
  hasEntry: (relativeFilePath: string) => boolean;
9
9
  getEntry: (relativeFilePath: string) => IndexEntry | undefined;
10
+ getKeys: () => MapIterator<string>;
10
11
  addEntry: (relativeFilePath: string, entry: IndexEntry) => void;
11
12
  removeEntry: (relativeFilePath: string) => void;
12
13
  };
@@ -1 +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"}
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;;iCAK/B,MAAM,SAAS,UAAU,KAAG,IAAI;oCAK7B,MAAM,KAAG,IAAI;CAI9C,CAAC"}
@@ -100,6 +100,7 @@ exports.dumpIndexHelper = {
100
100
  },
101
101
  hasEntry: (relativeFilePath) => index.has(relativeFilePath),
102
102
  getEntry: (relativeFilePath) => index.get(relativeFilePath),
103
+ getKeys: () => index.keys(),
103
104
  addEntry: (relativeFilePath, entry) => {
104
105
  setIsStale(true);
105
106
  index.set(relativeFilePath, entry);
@@ -1 +1 @@
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"}
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;AAqKjD,eAAO,MAAM,WAAW,EAAE,WA+EzB,CAAC"}
@@ -99,6 +99,48 @@ const removeDeletedFiles = (diff, dump, filesDumpDir) => {
99
99
  }
100
100
  });
101
101
  };
102
+ const removeStaleFiles = (diff, dump, filesDumpDir) => {
103
+ const iterator = dumpIndexHelper_1.dumpIndexHelper.getKeys();
104
+ for (const relativeFilepath of iterator) {
105
+ const absoluteFilepath = `${filesDumpDir}/${relativeFilepath}`;
106
+ if (!store_1.store.data.has(relativeFilepath) && fs_1.default.existsSync(absoluteFilepath)) {
107
+ logger_1.logger.info(`Dump: removing stale file: ${relativeFilepath}`);
108
+ try {
109
+ // Get old public URLs before they change on disk.
110
+ const dumpStaleFileString = fs_1.default
111
+ .readFileSync(absoluteFilepath)
112
+ .toString();
113
+ const isJson = (0, fs_2.isJsonFile)(relativeFilepath);
114
+ const dumpStaleFileContentData = isJson
115
+ ? JSON.parse(dumpStaleFileString)
116
+ : dumpStaleFileString;
117
+ let oldPublicUrl = dumpStaleFileContentData.data?.content?.url?.path || null;
118
+ // An stale file can be a manually copied file.
119
+ // In that case, that stale file would have an oldPublicUrl from a valid file,
120
+ // which would lead to deleting a valid URL.
121
+ // To solve that case, check that oldPublicUrl is not a valid URL.
122
+ if (oldPublicUrl && store_1.store.index.url.has(oldPublicUrl)) {
123
+ logger_1.logger.info(`Dump: skipping valid url from stale file: ${oldPublicUrl}`);
124
+ oldPublicUrl = null;
125
+ }
126
+ // Delete it.
127
+ fs_1.default.unlinkSync(absoluteFilepath);
128
+ // Delete any empty directory.
129
+ (0, fs_2.removeEmptyDirsUpwards)(path_1.default.dirname(absoluteFilepath));
130
+ // Delete it from index.
131
+ dumpIndexHelper_1.dumpIndexHelper.removeEntry(relativeFilepath);
132
+ // Mark it as deleted.
133
+ dump.deleted.set(relativeFilepath, {
134
+ oldPublicUrl,
135
+ newPublicUrl: null,
136
+ });
137
+ }
138
+ catch (e) {
139
+ logger_1.logger.error(`Dump: error deleting stale file "${absoluteFilepath}": ${e}`);
140
+ }
141
+ }
142
+ }
143
+ };
102
144
  exports.dumpManager = {
103
145
  dump(options = { incremental: true }) {
104
146
  const startDate = microtime_1.default.now();
@@ -120,6 +162,8 @@ exports.dumpManager = {
120
162
  storeUpdatedFiles(diff, dump, filesDumpDir);
121
163
  // Remove deleted files.
122
164
  removeDeletedFiles(diff, dump, filesDumpDir);
165
+ // Remove stale files.
166
+ removeStaleFiles(diff, dump, filesDumpDir);
123
167
  // Save dump index
124
168
  dumpIndexHelper_1.dumpIndexHelper.saveDumpIndex();
125
169
  // Invoke "onDumpCreate" hook.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@static-suite/static-suite-data-server",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
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",
@@ -84,5 +84,6 @@
84
84
  "src/__tests__/fixtures/*",
85
85
  "src/__tests__/mocks/*"
86
86
  ]
87
- }
87
+ },
88
+ "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
88
89
  }
@@ -5,8 +5,8 @@ import { jsonify } from '../../lib/utils/object';
5
5
  const diffIndex = (req: Request, res: Response): void => {
6
6
  res.render('diffIndex', {
7
7
  links: {
8
- '/diff/incremental': 'Execute an incremental dump',
9
- '/diff/full': 'Execute a full dump',
8
+ '/diff/incremental': 'Execute an incremental diff',
9
+ '/diff/full': 'Execute a full diff',
10
10
  '/diff/reset':
11
11
  'Clears intermediate changes tracked by dependency manager',
12
12
  },
@@ -1,7 +1,9 @@
1
1
  import { Request, Response } from 'express';
2
+ import { version } from '../../../package.json';
2
3
 
3
4
  export const home = (req: Request, res: Response): void => {
4
5
  res.render('home', {
6
+ version,
5
7
  links: {
6
8
  '/data': 'Browse all data loaded into the server',
7
9
  '/dependency': 'Dependency data',
@@ -4,7 +4,6 @@ import { queryIndex, runQuery } from './query';
4
4
  import { cacheIndex, cacheClear } from './cache';
5
5
  import {
6
6
  statusBasic,
7
- statusDiff,
8
7
  statusIndex,
9
8
  statusIndexCustom,
10
9
  statusIndexUrl,
@@ -42,7 +41,6 @@ routes.get('/status/basic', statusBasic);
42
41
  routes.get('/status/index/url', statusIndexUrl);
43
42
  routes.get('/status/index/uuid', statusIndexUuid);
44
43
  routes.get('/status/index/custom', statusIndexCustom);
45
- routes.get('/status/diff', statusDiff);
46
44
  routes.get('/status', statusIndex);
47
45
  routes.get('/query', queryIndex);
48
46
  routes.get('/query/*queryDefinition', runQuery);
@@ -5,8 +5,6 @@ import { queryRunner } from '../../lib/query';
5
5
  import { config } from '../../lib/config';
6
6
  import { cache } from '../../lib/utils/cache';
7
7
  import { store } from '../../lib/store';
8
- import { jsonify } from '../../lib/utils/object';
9
- import { diffManager } from '../../lib/store/diff/diffManager';
10
8
  import { ObjectType } from '../../lib/utils/object/object.types';
11
9
 
12
10
  const statusIndex = (req: Request, res: Response): void => {
@@ -17,7 +15,6 @@ const statusIndex = (req: Request, res: Response): void => {
17
15
  '/status/index/uuid': 'List of indexed UUIDs by language',
18
16
  '/status/index/include': 'List of indexed includes',
19
17
  '/status/index/custom': 'List of custom indexes',
20
- '/status/diff': 'Executes a diff operation',
21
18
  },
22
19
  });
23
20
  };
@@ -64,18 +61,10 @@ const statusIndexCustom = (req: Request, res: Response): void => {
64
61
  res.send(response);
65
62
  };
66
63
 
67
- const statusDiff = (req: Request, res: Response): void => {
68
- const response = jsonify(diffManager.getDiff());
69
- res.status(200);
70
- res.set({ 'Content-Type': 'application/json' });
71
- res.send(response);
72
- };
73
-
74
64
  export {
75
65
  statusIndex,
76
66
  statusBasic,
77
67
  statusIndexUrl,
78
68
  statusIndexUuid,
79
69
  statusIndexCustom,
80
- statusDiff,
81
70
  };
@@ -5,7 +5,7 @@ block vars
5
5
 
6
6
  block content
7
7
  h1(class="title is-1")="Available cache bins"
8
- table(class="table is-fullwidth is-hoverable")
8
+ table(class="table is-fullwidth is-hoverable")
9
9
  tbody
10
10
  if cacheBins.length
11
11
  each cacheBin in cacheBins
@@ -4,7 +4,7 @@ block vars
4
4
  - var title = "Static Suite Data Server"
5
5
 
6
6
  block content
7
- h1(class="title is-1")="Static Suite Data Server"
7
+ h1(class="title is-1")=`Static Suite Data Server ${version}`
8
8
  h2(class="subtitle")="Table of Contents"
9
9
  table(class="table is-fullwidth is-hoverable")
10
10
  tbody
@@ -1,3 +1,4 @@
1
+ import { version } from '../../package.json';
1
2
  import { configureLogger, logger } from './utils/logger';
2
3
  import { LogLevel, LogFile } from './utils/logger/logger.types';
3
4
  import { initWatcher } from './watcher';
@@ -72,7 +73,9 @@ const dataServer = {
72
73
  dumpIndexHelper.loadDumpIndex();
73
74
  }
74
75
 
75
- logger.info(`Data Server loaded in ${Date.now() - startDate}ms.`);
76
+ logger.info(
77
+ `Data Server ${version} loaded in ${Date.now() - startDate}ms.`,
78
+ );
76
79
 
77
80
  return {
78
81
  store,
@@ -120,6 +120,8 @@ export const dumpIndexHelper = {
120
120
  getEntry: (relativeFilePath: string): IndexEntry | undefined =>
121
121
  index.get(relativeFilePath),
122
122
 
123
+ getKeys: () => index.keys(),
124
+
123
125
  addEntry: (relativeFilePath: string, entry: IndexEntry): void => {
124
126
  setIsStale(true);
125
127
  index.set(relativeFilePath, entry);
@@ -116,6 +116,62 @@ const removeDeletedFiles = (
116
116
  });
117
117
  };
118
118
 
119
+ const removeStaleFiles = (
120
+ diff: Diff,
121
+ dump: Dump,
122
+ filesDumpDir: string,
123
+ ): void => {
124
+ const iterator = dumpIndexHelper.getKeys();
125
+ for (const relativeFilepath of iterator) {
126
+ const absoluteFilepath = `${filesDumpDir}/${relativeFilepath}`;
127
+ if (!store.data.has(relativeFilepath) && fs.existsSync(absoluteFilepath)) {
128
+ logger.info(`Dump: removing stale file: ${relativeFilepath}`);
129
+ try {
130
+ // Get old public URLs before they change on disk.
131
+ const dumpStaleFileString = fs
132
+ .readFileSync(absoluteFilepath)
133
+ .toString();
134
+ const isJson = isJsonFile(relativeFilepath);
135
+ const dumpStaleFileContentData = isJson
136
+ ? JSON.parse(dumpStaleFileString)
137
+ : dumpStaleFileString;
138
+ let oldPublicUrl: string | null =
139
+ dumpStaleFileContentData.data?.content?.url?.path || null;
140
+
141
+ // An stale file can be a manually copied file.
142
+ // In that case, that stale file would have an oldPublicUrl from a valid file,
143
+ // which would lead to deleting a valid URL.
144
+ // To solve that case, check that oldPublicUrl is not a valid URL.
145
+ if (oldPublicUrl && store.index.url.has(oldPublicUrl)) {
146
+ logger.info(
147
+ `Dump: skipping valid url from stale file: ${oldPublicUrl}`,
148
+ );
149
+ oldPublicUrl = null;
150
+ }
151
+
152
+ // Delete it.
153
+ fs.unlinkSync(absoluteFilepath);
154
+
155
+ // Delete any empty directory.
156
+ removeEmptyDirsUpwards(path.dirname(absoluteFilepath));
157
+
158
+ // Delete it from index.
159
+ dumpIndexHelper.removeEntry(relativeFilepath);
160
+
161
+ // Mark it as deleted.
162
+ dump.deleted.set(relativeFilepath, {
163
+ oldPublicUrl,
164
+ newPublicUrl: null,
165
+ });
166
+ } catch (e) {
167
+ logger.error(
168
+ `Dump: error deleting stale file "${absoluteFilepath}": ${e}`,
169
+ );
170
+ }
171
+ }
172
+ }
173
+ };
174
+
119
175
  export const dumpManager: DumpManager = {
120
176
  dump(options = { incremental: true }): Dump {
121
177
  const startDate = microtime.now();
@@ -143,6 +199,9 @@ export const dumpManager: DumpManager = {
143
199
  // Remove deleted files.
144
200
  removeDeletedFiles(diff, dump, filesDumpDir);
145
201
 
202
+ // Remove stale files.
203
+ removeStaleFiles(diff, dump, filesDumpDir);
204
+
146
205
  // Save dump index
147
206
  dumpIndexHelper.saveDumpIndex();
148
207