inibase 1.0.0-rc.75 → 1.0.0-rc.77
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/README.md +3 -3
- package/dist/cli.js +9 -1
- package/dist/index.d.ts +7 -20
- package/dist/index.js +107 -121
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -632,11 +632,11 @@ import Inibase from "inibase";
|
|
|
632
632
|
const db = new Inibase("/databaseName");
|
|
633
633
|
|
|
634
634
|
// order users by the age column
|
|
635
|
-
await db.
|
|
635
|
+
await db.get("user", undefined, { sort: "age" });
|
|
636
636
|
|
|
637
637
|
// order users by the age and username columns
|
|
638
|
-
await db.
|
|
639
|
-
await db.
|
|
638
|
+
await db.get("user", undefined, { sort: ["age", "username"] });
|
|
639
|
+
await db.get("user", undefined, { sort: {age: -1, username: "asc"} });
|
|
640
640
|
```
|
|
641
641
|
</blockquote>
|
|
642
642
|
</details>
|
package/dist/cli.js
CHANGED
|
@@ -196,7 +196,7 @@ rl.on("line", async (input) => {
|
|
|
196
196
|
console.log(`${textRed(" Err:")} Please specify table name`);
|
|
197
197
|
break;
|
|
198
198
|
}
|
|
199
|
-
let where = undefined, page = undefined, perPage = undefined, columns = undefined, data = undefined;
|
|
199
|
+
let where = undefined, page = undefined, perPage = undefined, columns = undefined, sort = undefined, data = undefined;
|
|
200
200
|
if (splitedInput.toSpliced(0, 1).length) {
|
|
201
201
|
const parsedArgs = parseArgs({
|
|
202
202
|
args: splitedInput.toSpliced(0, table ? 1 : 2),
|
|
@@ -204,6 +204,7 @@ rl.on("line", async (input) => {
|
|
|
204
204
|
where: { type: "string", short: "w" },
|
|
205
205
|
page: { type: "string", short: "p" },
|
|
206
206
|
perPage: { type: "string", short: "l" },
|
|
207
|
+
sort: { type: "string", short: "s" },
|
|
207
208
|
columns: { type: "string", short: "c", multiple: true },
|
|
208
209
|
data: { type: "string", short: "d" },
|
|
209
210
|
},
|
|
@@ -216,6 +217,12 @@ rl.on("line", async (input) => {
|
|
|
216
217
|
else if (isJSON(parsedArgs.where))
|
|
217
218
|
where = Inison.unstringify(parsedArgs.where);
|
|
218
219
|
}
|
|
220
|
+
if (parsedArgs.sort) {
|
|
221
|
+
if (isJSON(parsedArgs.sort))
|
|
222
|
+
sort = Inison.unstringify(parsedArgs.sort);
|
|
223
|
+
else
|
|
224
|
+
sort = parsedArgs.sort;
|
|
225
|
+
}
|
|
219
226
|
page = Number(parsedArgs.page) ?? undefined;
|
|
220
227
|
perPage = Number(parsedArgs.perPage) ?? undefined;
|
|
221
228
|
columns = parsedArgs.columns;
|
|
@@ -229,6 +236,7 @@ rl.on("line", async (input) => {
|
|
|
229
236
|
page: Number(page) ?? 1,
|
|
230
237
|
perPage: Number(perPage) ?? 15,
|
|
231
238
|
columns,
|
|
239
|
+
sort,
|
|
232
240
|
}));
|
|
233
241
|
break;
|
|
234
242
|
case "p":
|
package/dist/index.d.ts
CHANGED
|
@@ -21,7 +21,7 @@ export interface Options {
|
|
|
21
21
|
page?: number;
|
|
22
22
|
perPage?: number;
|
|
23
23
|
columns?: string[] | string;
|
|
24
|
-
|
|
24
|
+
sort?: Record<string, 1 | -1 | "asc" | "ASC" | "desc" | "DESC"> | string[] | string;
|
|
25
25
|
}
|
|
26
26
|
export interface Config {
|
|
27
27
|
compression?: boolean;
|
|
@@ -113,13 +113,14 @@ export default class Inibase {
|
|
|
113
113
|
* @param {string} tableName
|
|
114
114
|
* @param {(string | number | (string | number)[] | Criteria | undefined)} [where]
|
|
115
115
|
* @param {(Options | undefined)} [options]
|
|
116
|
-
* @param {
|
|
117
|
-
* @param {
|
|
118
|
-
* @param {boolean} [_skipIdColumn]
|
|
116
|
+
* @param {boolean} [onlyOne]
|
|
117
|
+
* @param {boolean} [onlyLinesNumbers]
|
|
119
118
|
* @return {*} {(Promise<Data[] | Data | number[] | null>)}
|
|
120
119
|
*/
|
|
121
|
-
get(tableName: string, where
|
|
122
|
-
get(tableName: string, where
|
|
120
|
+
get(tableName: string, where: string | number | (string | number)[] | Criteria | undefined, options: Options | undefined, onlyOne: true, onlyLinesNumbers?: false): Promise<Data | null>;
|
|
121
|
+
get(tableName: string, where: string | number, options?: Options, onlyOne?: boolean, onlyLinesNumbers?: false): Promise<Data | null>;
|
|
122
|
+
get(tableName: string, where?: string | number | (string | number)[] | Criteria, options?: Options, onlyOne?: boolean, onlyLinesNumbers?: false): Promise<Data[] | null>;
|
|
123
|
+
get(tableName: string, where: string | number | (string | number)[] | Criteria | undefined, options: Options | undefined, onlyOne: boolean | undefined, onlyLinesNumbers: true): Promise<number[]>;
|
|
123
124
|
/**
|
|
124
125
|
* Create new item(s) in a table
|
|
125
126
|
*
|
|
@@ -183,18 +184,4 @@ export default class Inibase {
|
|
|
183
184
|
*/
|
|
184
185
|
min(tableName: string, columns: string, where?: number | string | (number | string)[] | Criteria): Promise<number>;
|
|
185
186
|
min(tableName: string, columns: string[], where?: number | string | (number | string)[] | Criteria): Promise<Record<string, number>>;
|
|
186
|
-
/**
|
|
187
|
-
* Sort column(s) of a table
|
|
188
|
-
*
|
|
189
|
-
* @param {string} tableName
|
|
190
|
-
* @param {(string
|
|
191
|
-
* | string[]
|
|
192
|
-
* | Record<string, 1 | -1 | "asc" | "ASC" | "desc" | "DESC">)} columns
|
|
193
|
-
* @param {(string | number | (string | number)[] | Criteria)} [where]
|
|
194
|
-
* @param {Options} [options={
|
|
195
|
-
* page: 1,
|
|
196
|
-
* perPage: 15,
|
|
197
|
-
* }]
|
|
198
|
-
*/
|
|
199
|
-
sort(tableName: string, columns: string | string[] | Record<string, 1 | -1 | "asc" | "ASC" | "desc" | "DESC">, where?: string | number | (string | number)[] | Criteria, options?: Options): Promise<any[]>;
|
|
200
187
|
}
|
package/dist/index.js
CHANGED
|
@@ -222,30 +222,32 @@ export default class Inibase {
|
|
|
222
222
|
const schemaFile = await readFile(tableSchemaPath, "utf8");
|
|
223
223
|
if (!schemaFile)
|
|
224
224
|
return undefined;
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
return [
|
|
225
|
+
let schema = JSON.parse(schemaFile);
|
|
226
|
+
const lastIdNumber = UtilsServer.findLastIdNumber(schema, this.salt);
|
|
227
|
+
schema = [
|
|
229
228
|
{
|
|
230
|
-
id:
|
|
229
|
+
id: 0,
|
|
231
230
|
key: "id",
|
|
232
231
|
type: "id",
|
|
233
232
|
required: true,
|
|
234
233
|
},
|
|
235
|
-
...
|
|
234
|
+
...schema,
|
|
236
235
|
{
|
|
237
|
-
id:
|
|
236
|
+
id: lastIdNumber + 1,
|
|
238
237
|
key: "createdAt",
|
|
239
238
|
type: "date",
|
|
240
239
|
required: true,
|
|
241
240
|
},
|
|
242
241
|
{
|
|
243
|
-
id:
|
|
242
|
+
id: lastIdNumber + 2,
|
|
244
243
|
key: "updatedAt",
|
|
245
244
|
type: "date",
|
|
246
245
|
required: false,
|
|
247
246
|
},
|
|
248
247
|
];
|
|
248
|
+
if (!encodeIDs)
|
|
249
|
+
return schema;
|
|
250
|
+
return UtilsServer.encodeSchemaID(schema, this.salt);
|
|
249
251
|
}
|
|
250
252
|
async throwErrorIfTableEmpty(tableName) {
|
|
251
253
|
const table = await this.getTable(tableName);
|
|
@@ -794,16 +796,14 @@ export default class Inibase {
|
|
|
794
796
|
async get(tableName, where, options = {
|
|
795
797
|
page: 1,
|
|
796
798
|
perPage: 15,
|
|
797
|
-
}, onlyOne, onlyLinesNumbers
|
|
799
|
+
}, onlyOne, onlyLinesNumbers) {
|
|
798
800
|
const tablePath = join(this.databasePath, tableName);
|
|
799
801
|
// Ensure options.columns is an array
|
|
800
802
|
if (options.columns) {
|
|
801
803
|
options.columns = Array.isArray(options.columns)
|
|
802
804
|
? options.columns
|
|
803
805
|
: [options.columns];
|
|
804
|
-
if (
|
|
805
|
-
options.columns.length &&
|
|
806
|
-
!options.columns.includes("id"))
|
|
806
|
+
if (options.columns.length && !options.columns.includes("id"))
|
|
807
807
|
options.columns.push("id");
|
|
808
808
|
}
|
|
809
809
|
// Default values for page and perPage
|
|
@@ -821,6 +821,96 @@ export default class Inibase {
|
|
|
821
821
|
((Array.isArray(where) && !where.length) ||
|
|
822
822
|
(Utils.isObject(where) && !Object.keys(where).length)))
|
|
823
823
|
where = undefined;
|
|
824
|
+
if (options.sort) {
|
|
825
|
+
let sortArray, isLineNumbers = true, keepItems = [];
|
|
826
|
+
if (Utils.isObject(options.sort) && !Array.isArray(options.sort)) {
|
|
827
|
+
// {name: "ASC", age: "DESC"}
|
|
828
|
+
sortArray = Object.entries(options.sort).map(([key, value]) => [
|
|
829
|
+
key,
|
|
830
|
+
typeof value === "string" ? value.toLowerCase() === "asc" : value > 0,
|
|
831
|
+
]);
|
|
832
|
+
}
|
|
833
|
+
else
|
|
834
|
+
sortArray = []
|
|
835
|
+
.concat(options.sort)
|
|
836
|
+
.map((column) => [column, true]);
|
|
837
|
+
let cacheKey = "";
|
|
838
|
+
// Criteria
|
|
839
|
+
if (this.tables[tableName].config.cache)
|
|
840
|
+
cacheKey = UtilsServer.hashString(inspect(sortArray, { sorted: true }));
|
|
841
|
+
if (where) {
|
|
842
|
+
const lineNumbers = await this.get(tableName, where, undefined, undefined, true);
|
|
843
|
+
keepItems = Object.values((await File.get(join(tablePath, `id${this.getFileExtension(tableName)}`), lineNumbers, "number", undefined, this.salt)) ?? {}).map(Number);
|
|
844
|
+
isLineNumbers = false;
|
|
845
|
+
if (!keepItems.length)
|
|
846
|
+
throw this.throwError("NO_RESULTS", tableName);
|
|
847
|
+
keepItems = keepItems.slice((options.page - 1) * options.perPage, options.page * options.perPage);
|
|
848
|
+
}
|
|
849
|
+
if (!keepItems.length)
|
|
850
|
+
keepItems = Array.from({ length: options.perPage }, (_, index) => (options.page - 1) * options.perPage +
|
|
851
|
+
index +
|
|
852
|
+
1);
|
|
853
|
+
const filesPathes = [["id", true], ...sortArray].map((column) => join(tablePath, `${column[0]}${this.getFileExtension(tableName)}`));
|
|
854
|
+
for await (const path of filesPathes.slice(1))
|
|
855
|
+
if (!(await File.isExists(path)))
|
|
856
|
+
return null;
|
|
857
|
+
// Construct the paste command to merge files and filter lines by IDs
|
|
858
|
+
const pasteCommand = `paste ${filesPathes.join(" ")}`;
|
|
859
|
+
// Construct the sort command dynamically based on the number of files for sorting
|
|
860
|
+
const index = 2;
|
|
861
|
+
const sortColumns = sortArray
|
|
862
|
+
.map(([key, ascending], i) => {
|
|
863
|
+
const field = Utils.getField(key, schema);
|
|
864
|
+
if (field)
|
|
865
|
+
return `-k${i + index},${i + index}${Utils.isFieldType(["id", "number", "date"], field.type, field.children)
|
|
866
|
+
? "n"
|
|
867
|
+
: ""}${!ascending ? "r" : ""}`;
|
|
868
|
+
return "";
|
|
869
|
+
})
|
|
870
|
+
.join(" ");
|
|
871
|
+
const sortCommand = `sort ${sortColumns} -T=${join(tablePath, ".tmp")}`;
|
|
872
|
+
// Construct the awk command to keep only the specified lines after sorting
|
|
873
|
+
const awkCommand = isLineNumbers
|
|
874
|
+
? `awk '${keepItems.map((lineNumber) => `NR==${lineNumber}`).join(" || ")}'`
|
|
875
|
+
: `awk '${keepItems.map((id) => `$1 ~ /^${id} */`).join(" || ")}'`;
|
|
876
|
+
try {
|
|
877
|
+
if (cacheKey)
|
|
878
|
+
await File.lock(join(tablePath, ".tmp"), cacheKey);
|
|
879
|
+
// Combine && Execute the commands synchronously
|
|
880
|
+
const lines = (await UtilsServer.exec(this.tables[tableName].config.cache
|
|
881
|
+
? (await File.isExists(join(tablePath, ".cache", `${cacheKey}${this.fileExtension}`)))
|
|
882
|
+
? `${awkCommand} ${join(tablePath, ".cache", `${cacheKey}${this.fileExtension}`)}`
|
|
883
|
+
: `${pasteCommand} | ${sortCommand} -o ${join(tablePath, ".cache", `${cacheKey}${this.fileExtension}`)} && ${awkCommand} ${join(tablePath, ".cache", `${cacheKey}${this.fileExtension}`)}`
|
|
884
|
+
: `${pasteCommand} | ${sortCommand} | ${awkCommand}`, {
|
|
885
|
+
encoding: "utf-8",
|
|
886
|
+
})).stdout
|
|
887
|
+
.trim()
|
|
888
|
+
.split("\n");
|
|
889
|
+
// Parse the result and extract the specified lines
|
|
890
|
+
const outputArray = lines.map((line) => {
|
|
891
|
+
const splitedFileColumns = line.split("\t"); // Assuming tab-separated columns
|
|
892
|
+
const outputObject = {};
|
|
893
|
+
// Extract values for each file, including `id${this.getFileExtension(tableName)}`
|
|
894
|
+
filesPathes.forEach((fileName, index) => {
|
|
895
|
+
const field = Utils.getField(parse(fileName).name, schema);
|
|
896
|
+
if (field)
|
|
897
|
+
outputObject[field.key] = File.decode(splitedFileColumns[index], field?.type, field?.children, this.salt);
|
|
898
|
+
});
|
|
899
|
+
return outputObject;
|
|
900
|
+
});
|
|
901
|
+
const restOfColumns = await this.get(tableName, outputArray.map(({ id }) => id), (({ sort, ...rest }) => rest)(options));
|
|
902
|
+
return restOfColumns
|
|
903
|
+
? outputArray.map((item) => ({
|
|
904
|
+
...item,
|
|
905
|
+
...restOfColumns.find(({ id }) => id === item.id),
|
|
906
|
+
}))
|
|
907
|
+
: outputArray;
|
|
908
|
+
}
|
|
909
|
+
finally {
|
|
910
|
+
if (cacheKey)
|
|
911
|
+
await File.unlock(join(tablePath, ".tmp"), cacheKey);
|
|
912
|
+
}
|
|
913
|
+
}
|
|
824
914
|
if (!where) {
|
|
825
915
|
// Display all data
|
|
826
916
|
RETURN = Object.values(await this.getItemsFromSchema(tableName, schema, Array.from({ length: options.perPage }, (_, index) => (options.page - 1) * options.perPage +
|
|
@@ -861,6 +951,11 @@ export default class Inibase {
|
|
|
861
951
|
return Object.keys(lineNumbers).length
|
|
862
952
|
? Object.keys(lineNumbers).map(Number)
|
|
863
953
|
: null;
|
|
954
|
+
if (options.columns) {
|
|
955
|
+
options.columns = options.columns.filter((column) => column !== "id");
|
|
956
|
+
if (!options.columns?.length)
|
|
957
|
+
options.columns = undefined;
|
|
958
|
+
}
|
|
864
959
|
RETURN = Object.values((await this.getItemsFromSchema(tableName, schema, Object.keys(lineNumbers).map(Number), options)) ?? {});
|
|
865
960
|
if (!this.totalItems[`${tableName}-*`])
|
|
866
961
|
this.totalItems[`${tableName}-*`] = countItems;
|
|
@@ -1214,113 +1309,4 @@ export default class Inibase {
|
|
|
1214
1309
|
}
|
|
1215
1310
|
return RETURN;
|
|
1216
1311
|
}
|
|
1217
|
-
/**
|
|
1218
|
-
* Sort column(s) of a table
|
|
1219
|
-
*
|
|
1220
|
-
* @param {string} tableName
|
|
1221
|
-
* @param {(string
|
|
1222
|
-
* | string[]
|
|
1223
|
-
* | Record<string, 1 | -1 | "asc" | "ASC" | "desc" | "DESC">)} columns
|
|
1224
|
-
* @param {(string | number | (string | number)[] | Criteria)} [where]
|
|
1225
|
-
* @param {Options} [options={
|
|
1226
|
-
* page: 1,
|
|
1227
|
-
* perPage: 15,
|
|
1228
|
-
* }]
|
|
1229
|
-
*/
|
|
1230
|
-
async sort(tableName, columns, where, options = {
|
|
1231
|
-
page: 1,
|
|
1232
|
-
perPage: 15,
|
|
1233
|
-
}) {
|
|
1234
|
-
const tablePath = join(this.databasePath, tableName), schema = (await this.throwErrorIfTableEmpty(tableName)).schema;
|
|
1235
|
-
// Default values for page and perPage
|
|
1236
|
-
options.page = options.page || 1;
|
|
1237
|
-
options.perPage = options.perPage || 15;
|
|
1238
|
-
let sortArray, isLineNumbers = true, keepItems = [];
|
|
1239
|
-
if (Utils.isObject(columns) && !Array.isArray(columns)) {
|
|
1240
|
-
// {name: "ASC", age: "DESC"}
|
|
1241
|
-
sortArray = Object.entries(columns).map(([key, value]) => [
|
|
1242
|
-
key,
|
|
1243
|
-
typeof value === "string" ? value.toLowerCase() === "asc" : value > 0,
|
|
1244
|
-
]);
|
|
1245
|
-
}
|
|
1246
|
-
else {
|
|
1247
|
-
if (!Array.isArray(columns))
|
|
1248
|
-
columns = [columns];
|
|
1249
|
-
sortArray = columns.map((column) => [column, true]);
|
|
1250
|
-
}
|
|
1251
|
-
let cacheKey = "";
|
|
1252
|
-
// Criteria
|
|
1253
|
-
if (this.tables[tableName].config.cache)
|
|
1254
|
-
cacheKey = UtilsServer.hashString(inspect(sortArray, { sorted: true }));
|
|
1255
|
-
if (where) {
|
|
1256
|
-
const lineNumbers = await this.get(tableName, where, undefined, undefined, true);
|
|
1257
|
-
keepItems = Object.values((await File.get(join(tablePath, `id${this.getFileExtension(tableName)}`), lineNumbers, "number", undefined, this.salt)) ?? {}).map(Number);
|
|
1258
|
-
isLineNumbers = false;
|
|
1259
|
-
if (!keepItems.length)
|
|
1260
|
-
throw this.throwError("NO_RESULTS", tableName);
|
|
1261
|
-
keepItems = keepItems.slice((options.page - 1) * options.perPage, options.page * options.perPage);
|
|
1262
|
-
}
|
|
1263
|
-
if (!keepItems.length)
|
|
1264
|
-
keepItems = Array.from({ length: options.perPage }, (_, index) => (options.page - 1) * options.perPage +
|
|
1265
|
-
index +
|
|
1266
|
-
1);
|
|
1267
|
-
const filesPathes = [["id", true], ...sortArray].map((column) => join(tablePath, `${column[0]}${this.getFileExtension(tableName)}`));
|
|
1268
|
-
// Construct the paste command to merge files and filter lines by IDs
|
|
1269
|
-
const pasteCommand = `paste ${filesPathes.join(" ")}`;
|
|
1270
|
-
// Construct the sort command dynamically based on the number of files for sorting
|
|
1271
|
-
const index = 2;
|
|
1272
|
-
const sortColumns = sortArray
|
|
1273
|
-
.map(([key, ascending], i) => {
|
|
1274
|
-
const field = Utils.getField(key, schema);
|
|
1275
|
-
if (field)
|
|
1276
|
-
return `-k${i + index},${i + index}${field.type === "number" ? "n" : ""}${!ascending ? "r" : ""}`;
|
|
1277
|
-
return "";
|
|
1278
|
-
})
|
|
1279
|
-
.join(" ");
|
|
1280
|
-
const sortCommand = `sort ${sortColumns}`;
|
|
1281
|
-
// Construct the awk command to keep only the specified lines after sorting
|
|
1282
|
-
const awkCommand = isLineNumbers
|
|
1283
|
-
? `awk '${keepItems.map((line) => `NR==${line}`).join(" || ")}'`
|
|
1284
|
-
: `awk 'NR==${keepItems[0]}${keepItems
|
|
1285
|
-
.map((num) => `||NR==${num}`)
|
|
1286
|
-
.join("")}'`;
|
|
1287
|
-
try {
|
|
1288
|
-
if (cacheKey)
|
|
1289
|
-
await File.lock(join(tablePath, ".tmp"), cacheKey);
|
|
1290
|
-
// Combine the commands
|
|
1291
|
-
// Execute the command synchronously
|
|
1292
|
-
const lines = (await UtilsServer.exec(this.tables[tableName].config.cache
|
|
1293
|
-
? (await File.isExists(join(tablePath, ".cache", `${cacheKey}${this.fileExtension}`)))
|
|
1294
|
-
? `${awkCommand} ${join(tablePath, ".cache", `${cacheKey}${this.fileExtension}`)}`
|
|
1295
|
-
: `${pasteCommand} | ${sortCommand} -o ${join(tablePath, ".cache", `${cacheKey}${this.fileExtension}`)} && ${awkCommand} ${join(tablePath, ".cache", `${cacheKey}${this.fileExtension}`)}`
|
|
1296
|
-
: `${pasteCommand} | ${sortCommand} | ${awkCommand}`, {
|
|
1297
|
-
encoding: "utf-8",
|
|
1298
|
-
})).stdout
|
|
1299
|
-
.trim()
|
|
1300
|
-
.split("\n");
|
|
1301
|
-
// Parse the result and extract the specified lines
|
|
1302
|
-
const outputArray = lines.map((line) => {
|
|
1303
|
-
const splitedFileColumns = line.split("\t"); // Assuming tab-separated columns
|
|
1304
|
-
const outputObject = {};
|
|
1305
|
-
// Extract values for each file, including `id${this.getFileExtension(tableName)}`
|
|
1306
|
-
filesPathes.forEach((fileName, index) => {
|
|
1307
|
-
const field = Utils.getField(parse(fileName).name, schema);
|
|
1308
|
-
if (field)
|
|
1309
|
-
outputObject[field.key] = File.decode(splitedFileColumns[index], field?.type, field?.children, this.salt);
|
|
1310
|
-
});
|
|
1311
|
-
return outputObject;
|
|
1312
|
-
});
|
|
1313
|
-
const restOfColumns = await this.get(tableName, outputArray.map(({ id }) => id), options, undefined, undefined, true);
|
|
1314
|
-
return restOfColumns
|
|
1315
|
-
? outputArray.map((item, index) => ({
|
|
1316
|
-
...item,
|
|
1317
|
-
...restOfColumns[index],
|
|
1318
|
-
}))
|
|
1319
|
-
: outputArray;
|
|
1320
|
-
}
|
|
1321
|
-
finally {
|
|
1322
|
-
if (cacheKey)
|
|
1323
|
-
await File.unlock(join(tablePath, ".tmp"), cacheKey);
|
|
1324
|
-
}
|
|
1325
|
-
}
|
|
1326
1312
|
}
|