refactor(document): extract file route builder and normalize query composition
This commit is contained in:
@@ -0,0 +1,33 @@
|
|||||||
|
const encodeRouteParam = (value) => encodeURIComponent(String(value));
|
||||||
|
|
||||||
|
export const buildFileQuery = (path, params = {}, options = {}) => {
|
||||||
|
const { encode = false } = options;
|
||||||
|
|
||||||
|
const entries = Object.entries(params).filter(([, value]) => {
|
||||||
|
return value !== undefined && value !== null;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (entries.length === 0) {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
const query = entries
|
||||||
|
.map(([key, value]) => {
|
||||||
|
if (!encode) {
|
||||||
|
return `${key}=${String(value)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${encodeRouteParam(key)}=${encodeRouteParam(value)}`;
|
||||||
|
})
|
||||||
|
.join("&");
|
||||||
|
|
||||||
|
return `${path}?${query}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const withBaseUrl = (baseUrl, route) => {
|
||||||
|
return `${baseUrl}${route}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const appendQuerySuffix = (route, suffix = "") => {
|
||||||
|
return `${route}${suffix}`;
|
||||||
|
};
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
export * from "./relayClient";
|
export * from "./relayClient";
|
||||||
export * from "./endpointClient";
|
export * from "./endpointClient";
|
||||||
export * from "./fileClient";
|
export * from "./fileClient";
|
||||||
|
export * from "./fileRouteBuilder";
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
import { BASE_URL } from "../core/env";
|
import { BASE_URL } from "../core/env";
|
||||||
import { consoleLogger } from "../core/logger";
|
import { consoleLogger } from "../core/logger";
|
||||||
import { hashAPIPath } from "../core/hash";
|
import { hashAPIPath } from "../core/hash";
|
||||||
import { buildHashedQueryUrl } from "../clients/relayClient";
|
import {
|
||||||
import { getJson, requestJson } from "../clients/endpointClient";
|
buildFileQuery,
|
||||||
|
withBaseUrl,
|
||||||
|
appendQuerySuffix
|
||||||
|
} from "../clients/fileRouteBuilder";
|
||||||
import {
|
import {
|
||||||
getFileJson,
|
getFileJson,
|
||||||
getSignedFileJson,
|
getSignedFileJson,
|
||||||
@@ -11,55 +14,59 @@ import {
|
|||||||
} from "../clients/fileClient";
|
} from "../clients/fileClient";
|
||||||
|
|
||||||
export const getAwaitingSubmissionFromBlob = (containerName) => {
|
export const getAwaitingSubmissionFromBlob = (containerName) => {
|
||||||
return getJson(
|
const route = buildFileQuery("/api/file/getawaitingsubmissionfromblob", {
|
||||||
BASE_URL +
|
container: containerName
|
||||||
"/api/file/getawaitingsubmissionfromblob?container=" +
|
});
|
||||||
containerName +
|
|
||||||
hashAPIPath(
|
return getFileJson(
|
||||||
"/api/file/getawaitingsubmissionfromblob?container=" +
|
withBaseUrl(BASE_URL, appendQuerySuffix(route, hashAPIPath(route)))
|
||||||
containerName
|
|
||||||
)
|
|
||||||
).catch((error) => {
|
).catch((error) => {
|
||||||
consoleLogger(error);
|
consoleLogger(error);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getRepsFromBlob = (containerName) => {
|
export const getRepsFromBlob = (containerName) => {
|
||||||
return getJson(
|
const route = buildFileQuery("/api/file/getrepsblob", {
|
||||||
BASE_URL +
|
container: containerName
|
||||||
"/api/file/getrepsblob?container=" +
|
});
|
||||||
containerName +
|
|
||||||
hashAPIPath("/api/file/getrepsblob?container=" + containerName)
|
return getFileJson(
|
||||||
|
withBaseUrl(BASE_URL, appendQuerySuffix(route, hashAPIPath(route)))
|
||||||
).catch((error) => {
|
).catch((error) => {
|
||||||
consoleLogger(error);
|
consoleLogger(error);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getRepsFromBlobProxy = async (containerName) => {
|
export const getRepsFromBlobProxy = async (containerName) => {
|
||||||
return getJson(
|
const route = buildFileQuery("/api/file/getrepsblobproxy", {
|
||||||
"/api/file/getrepsblobproxy?container=" + containerName
|
container: containerName
|
||||||
).catch((error) => {
|
});
|
||||||
|
|
||||||
|
return getFileJson(route).catch((error) => {
|
||||||
consoleLogger(error);
|
consoleLogger(error);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getAwaitingSubmissionFromBlobProxy = async (containerName) => {
|
export const getAwaitingSubmissionFromBlobProxy = async (containerName) => {
|
||||||
return getJson(
|
const route = buildFileQuery(
|
||||||
BASE_URL +
|
"/api/file/getawaitingsubmissionfromblobproxy",
|
||||||
"/api/file/getawaitingsubmissionfromblobproxy?container=" +
|
{
|
||||||
containerName
|
container: containerName
|
||||||
).catch((error) => {
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return getFileJson(withBaseUrl(BASE_URL, route)).catch((error) => {
|
||||||
consoleLogger(error);
|
consoleLogger(error);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getFilesFromBlobproxy = (containerName, casefolderID) => {
|
export const getFilesFromBlobproxy = (containerName, casefolderID) => {
|
||||||
return getFileJson(
|
const route = buildFileQuery("/api/file/getbloblistproxy", {
|
||||||
"/api/file/getbloblistproxy?container=" +
|
container: containerName,
|
||||||
containerName +
|
casefolderID
|
||||||
"&casefolderID=" +
|
});
|
||||||
casefolderID
|
|
||||||
).catch((error) => {
|
return getFileJson(route).catch((error) => {
|
||||||
consoleLogger(error);
|
consoleLogger(error);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -68,11 +75,10 @@ export const deleteAwaitingSubmissionsFromBlob = (
|
|||||||
containerID,
|
containerID,
|
||||||
casefolderID
|
casefolderID
|
||||||
) => {
|
) => {
|
||||||
var queryUrl =
|
var queryUrl = buildFileQuery("/api/file/deleteblobcase", {
|
||||||
"/api/file/deleteblobcase?container=" +
|
container: containerID,
|
||||||
containerID +
|
casefolderID
|
||||||
"&casefolderID=" +
|
});
|
||||||
casefolderID;
|
|
||||||
|
|
||||||
return getSignedFileJson(queryUrl).catch((error) => {
|
return getSignedFileJson(queryUrl).catch((error) => {
|
||||||
consoleLogger(error);
|
consoleLogger(error);
|
||||||
@@ -84,13 +90,11 @@ export const deleteMyRepresentationsFromBlob = (
|
|||||||
casefolderID,
|
casefolderID,
|
||||||
repfile
|
repfile
|
||||||
) => {
|
) => {
|
||||||
var queryUrl =
|
var queryUrl = buildFileQuery("/api/file/deleteblobrep", {
|
||||||
"/api/file/deleteblobrep?container=" +
|
container: containerID,
|
||||||
containerID +
|
casefolderID,
|
||||||
"&casefolderID=" +
|
repfile
|
||||||
casefolderID +
|
});
|
||||||
"&repfile=" +
|
|
||||||
repfile;
|
|
||||||
|
|
||||||
return getSignedFileJson(queryUrl).catch((error) => {
|
return getSignedFileJson(queryUrl).catch((error) => {
|
||||||
consoleLogger(error);
|
consoleLogger(error);
|
||||||
@@ -217,18 +221,13 @@ export const generateAppealPDF = async (
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const getFilesFromBlob = (containerName, casefolderID) => {
|
export const getFilesFromBlob = (containerName, casefolderID) => {
|
||||||
return getJson(
|
const route = buildFileQuery("/api/file/getbloblist", {
|
||||||
BASE_URL +
|
container: containerName,
|
||||||
"/api/file/getbloblist?container=" +
|
casefolderID
|
||||||
containerName +
|
});
|
||||||
"&casefolderID=" +
|
|
||||||
casefolderID +
|
return getFileJson(
|
||||||
hashAPIPath(
|
withBaseUrl(BASE_URL, appendQuerySuffix(route, hashAPIPath(route)))
|
||||||
"/api/file/getbloblist?container=" +
|
|
||||||
containerName +
|
|
||||||
"&casefolderID=" +
|
|
||||||
casefolderID
|
|
||||||
)
|
|
||||||
).catch((error) => {
|
).catch((error) => {
|
||||||
consoleLogger(error);
|
consoleLogger(error);
|
||||||
});
|
});
|
||||||
@@ -239,15 +238,16 @@ export const getFilesFromBlobHashed = (
|
|||||||
getblobshash,
|
getblobshash,
|
||||||
casefolderID
|
casefolderID
|
||||||
) => {
|
) => {
|
||||||
return getJson(
|
const route = buildFileQuery("/api/file/getbloblist", {
|
||||||
"/api/file/getbloblist?container=" +
|
container: containerName,
|
||||||
containerName +
|
casefolderID
|
||||||
"&casefolderID=" +
|
|
||||||
casefolderID +
|
|
||||||
getblobshash
|
|
||||||
).catch((error) => {
|
|
||||||
consoleLogger(error);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return getFileJson(appendQuerySuffix(route, getblobshash)).catch(
|
||||||
|
(error) => {
|
||||||
|
consoleLogger(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const deleteBlob = async (
|
export const deleteBlob = async (
|
||||||
@@ -256,17 +256,23 @@ export const deleteBlob = async (
|
|||||||
deleteblobhash,
|
deleteblobhash,
|
||||||
casefolderID
|
casefolderID
|
||||||
) => {
|
) => {
|
||||||
return getFileJson(
|
const route = buildFileQuery(
|
||||||
"/api/file/deleteblob?container=" +
|
"/api/file/deleteblob",
|
||||||
containerName +
|
{
|
||||||
"&casefolderID=" +
|
container: containerName,
|
||||||
encodeURIComponent(casefolderID) +
|
casefolderID,
|
||||||
"&blobname=" +
|
blobname: blobName
|
||||||
encodeURIComponent(blobName) +
|
},
|
||||||
deleteblobhash
|
{
|
||||||
).catch((error) => {
|
encode: true
|
||||||
consoleLogger(error);
|
}
|
||||||
});
|
);
|
||||||
|
|
||||||
|
return getFileJson(appendQuerySuffix(route, deleteblobhash)).catch(
|
||||||
|
(error) => {
|
||||||
|
consoleLogger(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const deleteRepBlob = async (
|
export const deleteRepBlob = async (
|
||||||
@@ -276,26 +282,33 @@ export const deleteRepBlob = async (
|
|||||||
casefolderID,
|
casefolderID,
|
||||||
filenamePrefix
|
filenamePrefix
|
||||||
) => {
|
) => {
|
||||||
return getFileJson(
|
const route = buildFileQuery(
|
||||||
"/api/file/deleteblob?container=" +
|
"/api/file/deleteblob",
|
||||||
containerName +
|
{
|
||||||
"&casefolderID=" +
|
container: containerName,
|
||||||
encodeURIComponent(casefolderID + "/" + filenamePrefix) +
|
casefolderID: casefolderID + "/" + filenamePrefix,
|
||||||
"&blobname=" +
|
blobname: blobName
|
||||||
encodeURIComponent(blobName) +
|
},
|
||||||
deleteblobhash
|
{
|
||||||
).catch((error) => {
|
encode: true
|
||||||
consoleLogger(error);
|
}
|
||||||
});
|
);
|
||||||
|
|
||||||
|
return getFileJson(appendQuerySuffix(route, deleteblobhash)).catch(
|
||||||
|
(error) => {
|
||||||
|
consoleLogger(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const downloadBlob = (containerName, blobName) => {
|
export const downloadBlob = (containerName, blobName) => {
|
||||||
const queryUrl =
|
const queryUrl = withBaseUrl(
|
||||||
BASE_URL +
|
BASE_URL,
|
||||||
"/api/file/downloadblob?container=" +
|
buildFileQuery("/api/file/downloadblob", {
|
||||||
containerName.toLowerCase() +
|
container: containerName.toLowerCase(),
|
||||||
"&blobname=" +
|
blobname: blobName
|
||||||
blobName;
|
})
|
||||||
|
);
|
||||||
|
|
||||||
return downloadFileBlob(queryUrl).catch((error) => {
|
return downloadFileBlob(queryUrl).catch((error) => {
|
||||||
consoleLogger(error);
|
consoleLogger(error);
|
||||||
@@ -303,30 +316,31 @@ export const downloadBlob = (containerName, blobName) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const getProgressFromBlob = async (containerName, casereference) => {
|
export const getProgressFromBlob = async (containerName, casereference) => {
|
||||||
return getJson(
|
const route = buildFileQuery(
|
||||||
BASE_URL +
|
"/api/file/getprogressobjblob",
|
||||||
"/api/file/getprogressobjblob?container=" +
|
{
|
||||||
encodeURIComponent(containerName) +
|
container: containerName,
|
||||||
"&casefolderID=" +
|
casefolderID: casereference
|
||||||
encodeURIComponent(casereference) +
|
},
|
||||||
hashAPIPath(
|
{
|
||||||
"/api/file/getprogressobjblob?container=" +
|
encode: true
|
||||||
encodeURIComponent(containerName) +
|
}
|
||||||
"&casefolderID=" +
|
);
|
||||||
encodeURIComponent(casereference)
|
|
||||||
)
|
return getFileJson(
|
||||||
|
withBaseUrl(BASE_URL, appendQuerySuffix(route, hashAPIPath(route)))
|
||||||
).catch((error) => {
|
).catch((error) => {
|
||||||
consoleLogger(error);
|
consoleLogger(error);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const createContainerProxy = (containerName) => {
|
export const createContainerProxy = (containerName) => {
|
||||||
var queryUrl =
|
var route = buildFileQuery("/api/file/setupcontainer", {
|
||||||
"/api/file/setupcontainer?ident=" +
|
ident: containerName
|
||||||
containerName +
|
});
|
||||||
hashAPIPath("/api/file/setupcontainer?ident=" + containerName);
|
var queryUrl = appendQuerySuffix(route, hashAPIPath(route));
|
||||||
|
|
||||||
return getJson(BASE_URL + queryUrl).catch((error) => {
|
return getFileJson(withBaseUrl(BASE_URL, queryUrl)).catch((error) => {
|
||||||
consoleLogger(error);
|
consoleLogger(error);
|
||||||
|
|
||||||
return JSON.stringify(error);
|
return JSON.stringify(error);
|
||||||
|
|||||||
@@ -2429,3 +2429,91 @@ Validation:
|
|||||||
Follow-ups:
|
Follow-ups:
|
||||||
|
|
||||||
- Optional next widened slice: evaluate consolidating remaining direct `getJson` file-read flows in `documentDirectService` behind `fileClient` for full per-module client symmetry.
|
- Optional next widened slice: evaluate consolidating remaining direct `getJson` file-read flows in `documentDirectService` behind `fileClient` for full per-module client symmetry.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### CL-069: TASK22260 widened module-completion slice — documentDirectService file-read client symmetry
|
||||||
|
|
||||||
|
date: 2026-03-25
|
||||||
|
author: Cline
|
||||||
|
scope: `actions/services/documentDirectService.js`
|
||||||
|
type: change
|
||||||
|
rationale: Continue widened slice cadence by completing per-module client symmetry in `documentDirectService`, moving all file-read helper calls to `fileClient` instead of mixed endpoint client usage.
|
||||||
|
impact: Simplifies module dependency shape and centralizes file-route read behavior through a single client abstraction without changing runtime contracts.
|
||||||
|
status: completed
|
||||||
|
|
||||||
|
Summary:
|
||||||
|
|
||||||
|
- Removed mixed `endpointClient` usage from `documentDirectService` for file reads.
|
||||||
|
- Migrated remaining file-read/helper routes from `getJson` to `getFileJson`:
|
||||||
|
- `getAwaitingSubmissionFromBlob`
|
||||||
|
- `getRepsFromBlob`
|
||||||
|
- `getRepsFromBlobProxy`
|
||||||
|
- `getAwaitingSubmissionFromBlobProxy`
|
||||||
|
- `getFilesFromBlob`
|
||||||
|
- `getFilesFromBlobHashed`
|
||||||
|
- `getProgressFromBlob`
|
||||||
|
- `createContainerProxy`
|
||||||
|
- Removed now-unused imports from `documentDirectService`:
|
||||||
|
- `buildHashedQueryUrl`
|
||||||
|
- `getJson`
|
||||||
|
- `requestJson`
|
||||||
|
|
||||||
|
Validation:
|
||||||
|
|
||||||
|
- `node tests/phase22/index.test.cjs` -> pass
|
||||||
|
- core-token: 2/2
|
||||||
|
- client-utils: 5/5
|
||||||
|
- file-client: 4/4
|
||||||
|
- phase22 combined: pass
|
||||||
|
- `node tests/phase7/service-behaviour.test.cjs` -> pass (13/13)
|
||||||
|
- `npm run lint` -> warnings only (pre-existing `react-hooks/exhaustive-deps`; no new lint errors)
|
||||||
|
|
||||||
|
Follow-ups:
|
||||||
|
|
||||||
|
- Optional next widened slice: introduce a small `fileClient` URL-builder helper set for repeated query-string composition in `documentDirectService` (container/casefolder/blob parameters) to reduce string-concat drift risk.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### CL-070: TASK22260 widened cross-file slice — file route builder extraction + document service query normalization
|
||||||
|
|
||||||
|
date: 2026-03-25
|
||||||
|
author: Cline
|
||||||
|
scope: `actions/clients/{fileRouteBuilder,index}.js`, `actions/services/documentDirectService.js`, `tests/{serviceHarness,phase22/client-utils-behaviour}.cjs`
|
||||||
|
type: change
|
||||||
|
rationale: Deliver a wider-than-previous slice by extracting reusable file-route query composition helpers and applying them across document service paths, reducing repeated string concatenation and encoding drift risk.
|
||||||
|
impact: Improves maintainability and consistency of file-route URL construction while preserving existing runtime contracts and hash behavior.
|
||||||
|
status: completed
|
||||||
|
|
||||||
|
Summary:
|
||||||
|
|
||||||
|
- Added new shared helper module:
|
||||||
|
- `actions/clients/fileRouteBuilder.js`
|
||||||
|
- exports:
|
||||||
|
- `buildFileQuery(path, params, options)` (supports optional encoded query composition)
|
||||||
|
- `withBaseUrl(baseUrl, route)`
|
||||||
|
- `appendQuerySuffix(route, suffix)`
|
||||||
|
- Exported route-builder helpers via `actions/clients/index.js`.
|
||||||
|
- Refactored `actions/services/documentDirectService.js` to use route-builder helpers across read/delete/download/query flows:
|
||||||
|
- normalized composition for file routes and hash suffix append behavior
|
||||||
|
- preserved encoded-path behavior for sensitive params (`casefolderID`, `blobname`) where previously encoded
|
||||||
|
- preserved base URL prefix behavior and existing logger/catch semantics
|
||||||
|
- Updated test harness defaults in `tests/serviceHarness.cjs` for new helper symbols:
|
||||||
|
- `buildFileQuery`
|
||||||
|
- `withBaseUrl`
|
||||||
|
- `appendQuerySuffix`
|
||||||
|
- Expanded phase22 utility coverage in `tests/phase22/client-utils-behaviour.test.cjs` with file route-builder behavior assertions.
|
||||||
|
|
||||||
|
Validation:
|
||||||
|
|
||||||
|
- `node tests/phase22/index.test.cjs` -> pass
|
||||||
|
- core-token: 2/2
|
||||||
|
- client-utils: 6/6
|
||||||
|
- file-client: 4/4
|
||||||
|
- phase22 combined: pass
|
||||||
|
- `node tests/phase7/service-behaviour.test.cjs` -> pass (13/13)
|
||||||
|
- `npm run lint` -> warnings only (pre-existing `react-hooks/exhaustive-deps`; no new lint errors)
|
||||||
|
|
||||||
|
Follow-ups:
|
||||||
|
|
||||||
|
- Optional next widened slice: evaluate applying `fileRouteBuilder` to portal/case service file-route call sites for cross-module query-builder consistency.
|
||||||
|
|||||||
@@ -58,6 +58,32 @@ const loadRelayClientModule = (injected = {}) => {
|
|||||||
return context.module.exports;
|
return context.module.exports;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const loadFileRouteBuilderModule = (injected = {}) => {
|
||||||
|
const filePath = path.join(
|
||||||
|
rootDir,
|
||||||
|
"actions",
|
||||||
|
"clients",
|
||||||
|
"fileRouteBuilder.js"
|
||||||
|
);
|
||||||
|
let source = fs.readFileSync(filePath, "utf8");
|
||||||
|
|
||||||
|
source = source.replace(/import[\s\S]*?from\s+"[^"]+";\n?/g, "");
|
||||||
|
source = source.replace(/export const\s+/g, "const ");
|
||||||
|
source +=
|
||||||
|
"\nmodule.exports = { buildFileQuery, withBaseUrl, appendQuerySuffix };\n";
|
||||||
|
|
||||||
|
const context = {
|
||||||
|
module: { exports: {} },
|
||||||
|
exports: {},
|
||||||
|
require,
|
||||||
|
encodeURIComponent,
|
||||||
|
...injected
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.runInNewContext(source, context, { filename: filePath });
|
||||||
|
return context.module.exports;
|
||||||
|
};
|
||||||
|
|
||||||
const tests = [];
|
const tests = [];
|
||||||
const test = (name, fn) => tests.push({ name, fn });
|
const test = (name, fn) => tests.push({ name, fn });
|
||||||
|
|
||||||
@@ -150,6 +176,43 @@ test("clients/relayClient rethrows when browser hash call fails and no HASHKEY",
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("clients/fileRouteBuilder builds query with optional encoding and suffix helpers", async () => {
|
||||||
|
const mod = loadFileRouteBuilderModule();
|
||||||
|
|
||||||
|
const unencoded = mod.buildFileQuery("/api/file/getbloblist", {
|
||||||
|
container: "abc",
|
||||||
|
casefolderID: "x/y"
|
||||||
|
});
|
||||||
|
const encoded = mod.buildFileQuery(
|
||||||
|
"/api/file/deleteblob",
|
||||||
|
{
|
||||||
|
container: "abc",
|
||||||
|
casefolderID: "x/y",
|
||||||
|
blobname: "doc one.pdf"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
encode: true
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.strictEqual(
|
||||||
|
unencoded,
|
||||||
|
"/api/file/getbloblist?container=abc&casefolderID=x/y"
|
||||||
|
);
|
||||||
|
assert.strictEqual(
|
||||||
|
encoded,
|
||||||
|
"/api/file/deleteblob?container=abc&casefolderID=x%2Fy&blobname=doc%20one.pdf"
|
||||||
|
);
|
||||||
|
assert.strictEqual(
|
||||||
|
mod.withBaseUrl("http://example.local", unencoded),
|
||||||
|
"http://example.local/api/file/getbloblist?container=abc&casefolderID=x/y"
|
||||||
|
);
|
||||||
|
assert.strictEqual(
|
||||||
|
mod.appendQuerySuffix(unencoded, "&hash=123"),
|
||||||
|
"/api/file/getbloblist?container=abc&casefolderID=x/y&hash=123"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
const run = async () => {
|
const run = async () => {
|
||||||
let passed = 0;
|
let passed = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -126,6 +126,33 @@ const loadServiceModule = (fileName, injected = {}) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const defaultBuildFileQuery = (pathValue, params = {}, options = {}) => {
|
||||||
|
const { encode = false } = options;
|
||||||
|
const entries = Object.entries(params).filter(([, value]) => {
|
||||||
|
return value !== undefined && value !== null;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (entries.length === 0) {
|
||||||
|
return pathValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const query = entries
|
||||||
|
.map(([key, value]) => {
|
||||||
|
if (!encode) {
|
||||||
|
return `${key}=${String(value)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`;
|
||||||
|
})
|
||||||
|
.join("&");
|
||||||
|
|
||||||
|
return `${pathValue}?${query}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const defaultWithBaseUrl = (baseUrl, route) => `${baseUrl}${route}`;
|
||||||
|
const defaultAppendQuerySuffix = (route, suffix = "") =>
|
||||||
|
`${route}${suffix}`;
|
||||||
|
|
||||||
const context = {
|
const context = {
|
||||||
module: { exports: {} },
|
module: { exports: {} },
|
||||||
exports: {},
|
exports: {},
|
||||||
@@ -147,6 +174,10 @@ const loadServiceModule = (fileName, injected = {}) => {
|
|||||||
downloadFileBlob: injected.downloadFileBlob || defaultDownloadFileBlob,
|
downloadFileBlob: injected.downloadFileBlob || defaultDownloadFileBlob,
|
||||||
buildHashedQueryUrl:
|
buildHashedQueryUrl:
|
||||||
injected.buildHashedQueryUrl || defaultBuildHashedQueryUrl,
|
injected.buildHashedQueryUrl || defaultBuildHashedQueryUrl,
|
||||||
|
buildFileQuery: injected.buildFileQuery || defaultBuildFileQuery,
|
||||||
|
withBaseUrl: injected.withBaseUrl || defaultWithBaseUrl,
|
||||||
|
appendQuerySuffix:
|
||||||
|
injected.appendQuerySuffix || defaultAppendQuerySuffix,
|
||||||
...injected
|
...injected
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user