axiodb 14.2.7 → 15.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/Services/Auth/AuthSeeder.service.js +2 -3
- package/lib/Services/Auth/AuthSeeder.service.js.map +1 -1
- package/lib/Services/Auth/AuthService.service.d.ts +10 -1
- package/lib/Services/Auth/AuthService.service.js +20 -1
- package/lib/Services/Auth/AuthService.service.js.map +1 -1
- package/lib/Services/Database/database.operation.d.ts +15 -15
- package/lib/Services/Database/database.operation.js +43 -51
- package/lib/Services/Database/database.operation.js.map +1 -1
- package/lib/Services/Transaction/Transaction.service.js +3 -2
- package/lib/Services/Transaction/Transaction.service.js.map +1 -1
- package/lib/Services/Transaction/TransactionRegistry.service.d.ts +18 -0
- package/lib/Services/Transaction/TransactionRegistry.service.js +55 -24
- package/lib/Services/Transaction/TransactionRegistry.service.js.map +1 -1
- package/lib/Services/Transaction/WriteAheadLog.service.js +4 -14
- package/lib/Services/Transaction/WriteAheadLog.service.js.map +1 -1
- package/lib/config/Keys/Keys.d.ts +3 -0
- package/lib/config/Keys/Keys.js +3 -0
- package/lib/config/Keys/Keys.js.map +1 -1
- package/lib/engine/Filesystem/FileManager.d.ts +10 -0
- package/lib/engine/Filesystem/FileManager.js +27 -0
- package/lib/engine/Filesystem/FileManager.js.map +1 -1
- package/lib/server/config/keys.js +1 -1
- package/lib/server/config/keys.js.map +1 -1
- package/lib/server/controller/Auth/UserManagement.controller.js +6 -1
- package/lib/server/controller/Auth/UserManagement.controller.js.map +1 -1
- package/lib/server/controller/Collections/Collection.controller.js +3 -5
- package/lib/server/controller/Collections/Collection.controller.js.map +1 -1
- package/lib/server/controller/Database/Databse.controller.d.ts +9 -0
- package/lib/server/controller/Database/Databse.controller.js +122 -14
- package/lib/server/controller/Database/Databse.controller.js.map +1 -1
- package/lib/server/helper/databaseImport.helper.d.ts +37 -0
- package/lib/server/helper/databaseImport.helper.js +120 -0
- package/lib/server/helper/databaseImport.helper.js.map +1 -0
- package/lib/server/helper/documentCounterInFolder.helper.d.ts +12 -0
- package/lib/server/helper/{filesCounterInFolder.helper.js → documentCounterInFolder.helper.js} +16 -15
- package/lib/server/helper/documentCounterInFolder.helper.js.map +1 -0
- package/lib/server/public/AxioControl/.vite/manifest.json +2 -2
- package/lib/server/public/AxioControl/.vite/ssr-manifest.json +442 -15
- package/lib/server/public/AxioControl/assets/index-DkwtNvzk.js +157 -0
- package/lib/server/public/AxioControl/assets/index-DwPXIyl2.css +1 -0
- package/lib/server/public/AxioControl/index.html +2 -2
- package/lib/server/public/AxioControl/sw.js +1 -1
- package/lib/server/router/Router.js +54 -0
- package/lib/server/router/Router.js.map +1 -1
- package/lib/server/router/Routers/DB.routes.js +12 -1
- package/lib/server/router/Routers/DB.routes.js.map +1 -1
- package/lib/utility/ZipUnzip.utils.d.ts +35 -1
- package/lib/utility/ZipUnzip.utils.js +132 -12
- package/lib/utility/ZipUnzip.utils.js.map +1 -1
- package/package.json +1 -3
- package/lib/server/helper/filesCounterInFolder.helper.d.ts +0 -1
- package/lib/server/helper/filesCounterInFolder.helper.js.map +0 -1
- package/lib/server/public/AxioControl/assets/index-05O5admf.css +0 -1
- package/lib/server/public/AxioControl/assets/index-Ddne1B8d.js +0 -75
|
@@ -50,8 +50,11 @@ const StatusCode_1 = require("../../../config/Keys/StatusCode");
|
|
|
50
50
|
const responseBuilder_helper_1 = __importDefault(require("../../helper/responseBuilder.helper"));
|
|
51
51
|
const ZipUnzip_utils_1 = require("../../../utility/ZipUnzip.utils");
|
|
52
52
|
const fs_1 = __importDefault(require("fs"));
|
|
53
|
+
const os_1 = __importDefault(require("os"));
|
|
53
54
|
const path_1 = __importDefault(require("path"));
|
|
55
|
+
const promises_1 = require("node:stream/promises");
|
|
54
56
|
const Permissions_1 = require("../../../config/Keys/Permissions");
|
|
57
|
+
const databaseImport_helper_1 = require("../../helper/databaseImport.helper");
|
|
55
58
|
class DatabaseController {
|
|
56
59
|
constructor(AxioDBInstance) {
|
|
57
60
|
this.AxioDBInstance = AxioDBInstance;
|
|
@@ -180,35 +183,140 @@ class DatabaseController {
|
|
|
180
183
|
}
|
|
181
184
|
});
|
|
182
185
|
}
|
|
186
|
+
/**
|
|
187
|
+
* Imports a database from an uploaded .tar.gz.
|
|
188
|
+
*
|
|
189
|
+
* Everything is staged outside the data directory and proven to be a genuine AxioDB
|
|
190
|
+
* export before a single byte is promoted into place. That ordering is what lets a bad
|
|
191
|
+
* upload be discarded completely: an archive that fails validation never existed as far
|
|
192
|
+
* as the live data directory is concerned, so there is no partial database to clean up.
|
|
193
|
+
*/
|
|
183
194
|
importDatabase(request, reply) {
|
|
184
195
|
return __awaiter(this, void 0, void 0, function* () {
|
|
196
|
+
var _a;
|
|
197
|
+
var _b;
|
|
198
|
+
const username = (_b = (_a = request.authUser) === null || _a === void 0 ? void 0 : _a.username) !== null && _b !== void 0 ? _b : "another user";
|
|
185
199
|
const data = yield request.file();
|
|
186
200
|
if (!data) {
|
|
187
|
-
return reply.status(400).send({
|
|
188
|
-
success: false,
|
|
189
|
-
message: "No file uploaded",
|
|
190
|
-
});
|
|
201
|
+
return reply.status(400).send({ success: false, message: "No file uploaded" });
|
|
191
202
|
}
|
|
192
|
-
|
|
203
|
+
// A cheap pre-check on the filename. The authoritative check is on the archive's
|
|
204
|
+
// contents further down - a file can be named anything.
|
|
205
|
+
const uploadedArchiveName = path_1.default
|
|
206
|
+
.basename(data.filename)
|
|
207
|
+
.replace(/\.(tar\.gz|tgz|tar|gz|zip)$/i, "");
|
|
193
208
|
if ((0, Permissions_1.isReservedDatabaseName)(uploadedArchiveName)) {
|
|
194
209
|
return reply.status(403).send({
|
|
195
210
|
success: false,
|
|
196
211
|
message: "This is a reserved system database",
|
|
197
212
|
});
|
|
198
213
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
214
|
+
// Every import gets its own staging directory, so two people importing different
|
|
215
|
+
// databases at the same time never share state.
|
|
216
|
+
const workDir = yield fs_1.default.promises.mkdtemp(path_1.default.join(os_1.default.tmpdir(), "axiodb-import-"));
|
|
217
|
+
const stagingDir = path_1.default.join(workDir, "extracted");
|
|
218
|
+
yield fs_1.default.promises.mkdir(stagingDir);
|
|
219
|
+
let claimed = null;
|
|
220
|
+
try {
|
|
221
|
+
// Only the basename is used, so a crafted "../../" filename cannot escape workDir.
|
|
222
|
+
const savePath = path_1.default.join(workDir, path_1.default.basename(data.filename));
|
|
223
|
+
yield (0, promises_1.pipeline)(data.file, fs_1.default.createWriteStream(savePath));
|
|
224
|
+
if (data.file.truncated) {
|
|
225
|
+
return reply.status(413).send({
|
|
226
|
+
success: false,
|
|
227
|
+
message: "Upload was truncated before it finished.",
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
try {
|
|
231
|
+
// Extracted into staging, never straight into the data directory.
|
|
232
|
+
yield (0, ZipUnzip_utils_1.unzipFile)(savePath, stagingDir);
|
|
233
|
+
}
|
|
234
|
+
catch (error) {
|
|
235
|
+
console.error("Error unzipping uploaded database:", error);
|
|
236
|
+
return reply.status(400).send({
|
|
237
|
+
success: false,
|
|
238
|
+
message: error instanceof ZipUnzip_utils_1.UnsafeArchiveError
|
|
239
|
+
? error.message
|
|
240
|
+
: "Could not read that file as a .tar.gz archive. Upload the file produced by Export.",
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
// The database name comes from the archive's contents, not its filename: the same
|
|
244
|
+
// export can arrive under any name, and two names can hold the same database.
|
|
245
|
+
let databaseName;
|
|
246
|
+
try {
|
|
247
|
+
databaseName = (0, databaseImport_helper_1.readExportedDatabaseName)(stagingDir);
|
|
248
|
+
}
|
|
249
|
+
catch (error) {
|
|
250
|
+
console.error("Rejected upload that is not an AxioDB export:", error);
|
|
251
|
+
return reply.status(400).send({
|
|
252
|
+
success: false,
|
|
253
|
+
message: error instanceof databaseImport_helper_1.InvalidExportError
|
|
254
|
+
? error.message
|
|
255
|
+
: "That file is not an AxioDB database export.",
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
if ((0, Permissions_1.isReservedDatabaseName)(databaseName)) {
|
|
259
|
+
return reply.status(403).send({
|
|
260
|
+
success: false,
|
|
261
|
+
message: `"${databaseName}" is a reserved system database`,
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
// Claim before touching the destination, so a second importer of the same database is
|
|
265
|
+
// turned away rather than racing this one into the same directory.
|
|
266
|
+
try {
|
|
267
|
+
(0, databaseImport_helper_1.claimImport)(databaseName, username);
|
|
268
|
+
claimed = databaseName;
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
return reply.status(409).send({
|
|
272
|
+
success: false,
|
|
273
|
+
message: error instanceof databaseImport_helper_1.ImportConflictError
|
|
274
|
+
? error.message
|
|
275
|
+
: "That database is already being imported.",
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
const destination = path_1.default.join(this.AxioDBInstance.GetPath, databaseName);
|
|
279
|
+
if (fs_1.default.existsSync(destination)) {
|
|
280
|
+
return reply.status(409).send({
|
|
281
|
+
success: false,
|
|
282
|
+
message: `"${databaseName}" already exists on this instance. Delete it first if you want to replace it.`,
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
const source = path_1.default.join(stagingDir, databaseName);
|
|
286
|
+
try {
|
|
287
|
+
yield fs_1.default.promises.rename(source, destination);
|
|
288
|
+
}
|
|
289
|
+
catch (error) {
|
|
290
|
+
// Staging lives in the OS temp directory, which is frequently a different
|
|
291
|
+
// filesystem - rename cannot cross one, so fall back to a copy.
|
|
292
|
+
if ((error === null || error === void 0 ? void 0 : error.code) !== "EXDEV")
|
|
293
|
+
throw error;
|
|
294
|
+
yield fs_1.default.promises.cp(source, destination, { recursive: true });
|
|
295
|
+
}
|
|
296
|
+
return {
|
|
297
|
+
message: "Database imported successfully",
|
|
298
|
+
database: databaseName,
|
|
299
|
+
file: data.filename,
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
catch (error) {
|
|
303
|
+
console.error("Error importing database:", error);
|
|
205
304
|
return reply.status(500).send({
|
|
206
305
|
success: false,
|
|
207
|
-
message: "Error
|
|
306
|
+
message: "Error importing database",
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
finally {
|
|
310
|
+
if (claimed !== null)
|
|
311
|
+
(0, databaseImport_helper_1.releaseImport)(claimed);
|
|
312
|
+
// Discards the upload and everything extracted from it, on every path - success,
|
|
313
|
+
// rejection, or crash. Nothing an invalid archive produced survives this.
|
|
314
|
+
yield fs_1.default.promises
|
|
315
|
+
.rm(workDir, { recursive: true, force: true })
|
|
316
|
+
.catch((cleanupError) => {
|
|
317
|
+
console.error("Error cleaning up import staging directory:", cleanupError);
|
|
208
318
|
});
|
|
209
319
|
}
|
|
210
|
-
yield fs_1.default.promises.rmdir(tempDir, { recursive: true });
|
|
211
|
-
return { message: "File uploaded successfully", file: data.filename };
|
|
212
320
|
});
|
|
213
321
|
}
|
|
214
322
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Databse.controller.js","sourceRoot":"","sources":["../../../../source/server/controller/Database/Databse.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uDAAuD;AACvD,gEAA8D;AAE9D,iGAE6C;AAE7C,
|
|
1
|
+
{"version":3,"file":"Databse.controller.js","sourceRoot":"","sources":["../../../../source/server/controller/Database/Databse.controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Import staging: validating an uploaded archive before any of it reaches the live data
|
|
3
|
+
* directory, and serialising concurrent imports of the same database.
|
|
4
|
+
*/
|
|
5
|
+
/** Thrown when an upload is not a genuine AxioDB export. Callers answer 400. */
|
|
6
|
+
export declare class InvalidExportError extends Error {
|
|
7
|
+
constructor(message: string);
|
|
8
|
+
}
|
|
9
|
+
/** Thrown when the same database is already present or already being imported. Answer 409. */
|
|
10
|
+
export declare class ImportConflictError extends Error {
|
|
11
|
+
constructor(message: string);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Confirms that a staged directory holds one AxioDB database export, and returns its name.
|
|
15
|
+
*
|
|
16
|
+
* The database name comes from the archive's own contents, never from the uploaded
|
|
17
|
+
* filename - two people can export the same database and rename the file to anything, so
|
|
18
|
+
* the filename says nothing about what is inside.
|
|
19
|
+
*
|
|
20
|
+
* `tarGzFolder` archives `{root}/{dbName}`, so a genuine export is exactly one top-level
|
|
21
|
+
* directory containing recognisable AxioDB artefacts.
|
|
22
|
+
*
|
|
23
|
+
* @param stagingDir - Directory the archive was extracted into.
|
|
24
|
+
* @returns The database name the archive contains.
|
|
25
|
+
* @throws {InvalidExportError} When the contents are not an AxioDB export.
|
|
26
|
+
*/
|
|
27
|
+
export declare function readExportedDatabaseName(stagingDir: string): string;
|
|
28
|
+
/**
|
|
29
|
+
* Claims the right to import `databaseName`.
|
|
30
|
+
*
|
|
31
|
+
* @param databaseName - Name read from the archive's contents.
|
|
32
|
+
* @param username - Who is importing, so a clash can name them.
|
|
33
|
+
* @throws {ImportConflictError} When another import of the same database is in flight.
|
|
34
|
+
*/
|
|
35
|
+
export declare function claimImport(databaseName: string, username: string): void;
|
|
36
|
+
/** Releases the claim. Always call from a `finally`. */
|
|
37
|
+
export declare function releaseImport(databaseName: string): void;
|
|
@@ -0,0 +1,120 @@
|
|
|
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.ImportConflictError = exports.InvalidExportError = void 0;
|
|
7
|
+
exports.readExportedDatabaseName = readExportedDatabaseName;
|
|
8
|
+
exports.claimImport = claimImport;
|
|
9
|
+
exports.releaseImport = releaseImport;
|
|
10
|
+
const fs_1 = __importDefault(require("fs"));
|
|
11
|
+
const path_1 = __importDefault(require("path"));
|
|
12
|
+
const Keys_1 = require("../../config/Keys/Keys");
|
|
13
|
+
/**
|
|
14
|
+
* Import staging: validating an uploaded archive before any of it reaches the live data
|
|
15
|
+
* directory, and serialising concurrent imports of the same database.
|
|
16
|
+
*/
|
|
17
|
+
/** Thrown when an upload is not a genuine AxioDB export. Callers answer 400. */
|
|
18
|
+
class InvalidExportError extends Error {
|
|
19
|
+
constructor(message) {
|
|
20
|
+
super(message);
|
|
21
|
+
this.name = "InvalidExportError";
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.InvalidExportError = InvalidExportError;
|
|
25
|
+
/** Thrown when the same database is already present or already being imported. Answer 409. */
|
|
26
|
+
class ImportConflictError extends Error {
|
|
27
|
+
constructor(message) {
|
|
28
|
+
super(message);
|
|
29
|
+
this.name = "ImportConflictError";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.ImportConflictError = ImportConflictError;
|
|
33
|
+
/**
|
|
34
|
+
* Confirms that a staged directory holds one AxioDB database export, and returns its name.
|
|
35
|
+
*
|
|
36
|
+
* The database name comes from the archive's own contents, never from the uploaded
|
|
37
|
+
* filename - two people can export the same database and rename the file to anything, so
|
|
38
|
+
* the filename says nothing about what is inside.
|
|
39
|
+
*
|
|
40
|
+
* `tarGzFolder` archives `{root}/{dbName}`, so a genuine export is exactly one top-level
|
|
41
|
+
* directory containing recognisable AxioDB artefacts.
|
|
42
|
+
*
|
|
43
|
+
* @param stagingDir - Directory the archive was extracted into.
|
|
44
|
+
* @returns The database name the archive contains.
|
|
45
|
+
* @throws {InvalidExportError} When the contents are not an AxioDB export.
|
|
46
|
+
*/
|
|
47
|
+
function readExportedDatabaseName(stagingDir) {
|
|
48
|
+
const entries = fs_1.default.readdirSync(stagingDir, { withFileTypes: true });
|
|
49
|
+
const directories = entries.filter((entry) => entry.isDirectory());
|
|
50
|
+
const strayFiles = entries.filter((entry) => !entry.isDirectory());
|
|
51
|
+
if (directories.length === 0) {
|
|
52
|
+
throw new InvalidExportError("That archive contains no database folder. Upload the file produced by Export.");
|
|
53
|
+
}
|
|
54
|
+
if (directories.length > 1 || strayFiles.length > 0) {
|
|
55
|
+
throw new InvalidExportError("That archive holds more than one top-level item. An AxioDB export contains exactly one database folder.");
|
|
56
|
+
}
|
|
57
|
+
const databaseName = directories[0].name;
|
|
58
|
+
const databaseDir = path_1.default.join(stagingDir, databaseName);
|
|
59
|
+
if (!/^[a-zA-Z0-9_-]+$/.test(databaseName)) {
|
|
60
|
+
throw new InvalidExportError(`"${databaseName}" is not a usable database name.`);
|
|
61
|
+
}
|
|
62
|
+
// Allowlist rather than a presence check: a database that has no collections yet is a
|
|
63
|
+
// legitimate export and contains nothing at all, so "must contain X" would reject it.
|
|
64
|
+
// Asking instead that it contain *nothing but* AxioDB shapes accepts the empty case while
|
|
65
|
+
// still rejecting a folder of holiday photos.
|
|
66
|
+
for (const entry of fs_1.default.readdirSync(databaseDir, { withFileTypes: true })) {
|
|
67
|
+
if (entry.isFile()) {
|
|
68
|
+
if (entry.name !== Keys_1.General.Collection_Meta_File) {
|
|
69
|
+
throw new InvalidExportError(`"${databaseName}" is not an AxioDB export - it contains an unexpected file "${entry.name}".`);
|
|
70
|
+
}
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (!entry.isDirectory()) {
|
|
74
|
+
throw new InvalidExportError(`"${databaseName}" contains "${entry.name}", which is neither a file nor a collection folder.`);
|
|
75
|
+
}
|
|
76
|
+
// Each subdirectory must look like a collection: documents, indexes, or WAL, and
|
|
77
|
+
// nothing else. An empty collection folder is fine.
|
|
78
|
+
const collectionDir = path_1.default.join(databaseDir, entry.name);
|
|
79
|
+
for (const child of fs_1.default.readdirSync(collectionDir, { withFileTypes: true })) {
|
|
80
|
+
const isDocument = child.isFile() && child.name.endsWith(Keys_1.General.DBMS_File_EXT);
|
|
81
|
+
const isInternalDir = child.isDirectory() && (child.name === "indexes" || child.name === ".transactions");
|
|
82
|
+
if (!isDocument && !isInternalDir) {
|
|
83
|
+
throw new InvalidExportError(`"${databaseName}/${entry.name}" is not an AxioDB collection - it contains "${child.name}".`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return databaseName;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* In-process registry of imports currently in flight, keyed by database name.
|
|
91
|
+
*
|
|
92
|
+
* Two people importing *different* databases run concurrently and never meet - each gets
|
|
93
|
+
* its own staging directory. Two people importing the *same* database must not, because
|
|
94
|
+
* both would write the same destination: the second is told who has it instead.
|
|
95
|
+
*
|
|
96
|
+
* A Map is sufficient because AxioDB is a hard singleton - one process owns the data
|
|
97
|
+
* directory, so there is no second server to coordinate with.
|
|
98
|
+
*/
|
|
99
|
+
const activeImports = new Map();
|
|
100
|
+
/**
|
|
101
|
+
* Claims the right to import `databaseName`.
|
|
102
|
+
*
|
|
103
|
+
* @param databaseName - Name read from the archive's contents.
|
|
104
|
+
* @param username - Who is importing, so a clash can name them.
|
|
105
|
+
* @throws {ImportConflictError} When another import of the same database is in flight.
|
|
106
|
+
*/
|
|
107
|
+
function claimImport(databaseName, username) {
|
|
108
|
+
const holder = activeImports.get(databaseName);
|
|
109
|
+
if (holder !== undefined) {
|
|
110
|
+
throw new ImportConflictError(holder === username
|
|
111
|
+
? `You already have an import of "${databaseName}" running.`
|
|
112
|
+
: `"${databaseName}" is currently being imported by ${holder}. Try again once that finishes.`);
|
|
113
|
+
}
|
|
114
|
+
activeImports.set(databaseName, username);
|
|
115
|
+
}
|
|
116
|
+
/** Releases the claim. Always call from a `finally`. */
|
|
117
|
+
function releaseImport(databaseName) {
|
|
118
|
+
activeImports.delete(databaseName);
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=databaseImport.helper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"databaseImport.helper.js","sourceRoot":"","sources":["../../../source/server/helper/databaseImport.helper.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Counts the real documents stored directly in a collection folder.
|
|
3
|
+
*
|
|
4
|
+
* Documents are flat `.axiodb` files in the collection root. Everything else
|
|
5
|
+
* that lives there - the `indexes/` folder, `.transactions/` WAL staging, meta
|
|
6
|
+
* files - is internal bookkeeping and must not be counted, which is why this is
|
|
7
|
+
* neither recursive nor extension-agnostic.
|
|
8
|
+
*
|
|
9
|
+
* @param folderPath - Absolute path to the collection folder.
|
|
10
|
+
* @returns Number of documents in that collection.
|
|
11
|
+
*/
|
|
12
|
+
export default function countDocumentsInFolder(folderPath: string): Promise<number>;
|
package/lib/server/helper/{filesCounterInFolder.helper.js → documentCounterInFolder.helper.js}
RENAMED
|
@@ -12,23 +12,24 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.default =
|
|
15
|
+
exports.default = countDocumentsInFolder;
|
|
16
16
|
const promises_1 = __importDefault(require("node:fs/promises"));
|
|
17
|
-
const
|
|
18
|
-
|
|
17
|
+
const Keys_1 = require("../../config/Keys/Keys");
|
|
18
|
+
/**
|
|
19
|
+
* Counts the real documents stored directly in a collection folder.
|
|
20
|
+
*
|
|
21
|
+
* Documents are flat `.axiodb` files in the collection root. Everything else
|
|
22
|
+
* that lives there - the `indexes/` folder, `.transactions/` WAL staging, meta
|
|
23
|
+
* files - is internal bookkeeping and must not be counted, which is why this is
|
|
24
|
+
* neither recursive nor extension-agnostic.
|
|
25
|
+
*
|
|
26
|
+
* @param folderPath - Absolute path to the collection folder.
|
|
27
|
+
* @returns Number of documents in that collection.
|
|
28
|
+
*/
|
|
29
|
+
function countDocumentsInFolder(folderPath) {
|
|
19
30
|
return __awaiter(this, void 0, void 0, function* () {
|
|
20
|
-
let count = 0;
|
|
21
31
|
const items = yield promises_1.default.readdir(folderPath, { withFileTypes: true });
|
|
22
|
-
|
|
23
|
-
const fullPath = node_path_1.default.join(folderPath, item.name);
|
|
24
|
-
if (item.isFile()) {
|
|
25
|
-
count++;
|
|
26
|
-
}
|
|
27
|
-
else if (item.isDirectory()) {
|
|
28
|
-
count += yield countFilesRecursive(fullPath);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
return count;
|
|
32
|
+
return items.filter((item) => item.isFile() && item.name.endsWith(Keys_1.General.DBMS_File_EXT)).length;
|
|
32
33
|
});
|
|
33
34
|
}
|
|
34
|
-
//# sourceMappingURL=
|
|
35
|
+
//# sourceMappingURL=documentCounterInFolder.helper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documentCounterInFolder.helper.js","sourceRoot":"","sources":["../../../source/server/helper/documentCounterInFolder.helper.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,gEAAkC;AAClC,iDAAiD;AAEjD;;;;;;;;;;GAUG;AACH,gCACE,UAAkB;;QAElB,MAAM,KAAK,GAAG,MAAM,kBAAE,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QACpE,OAAO,KAAK,CAAC,MAAM,CACjB,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAO,CAAC,aAAa,CAAC,CACrE,CAAC,MAAM,CAAC;IACX,CAAC;CAAA"}
|