@localazy/strapi-plugin 1.1.3 → 1.4.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/dist/_chunks/{FetchIdentity-Dl2vx6zB.js → FetchIdentity-BpFOT163.js} +2 -2
- package/dist/_chunks/{FetchIdentity-C8-hFqEW.mjs → FetchIdentity-Cor4ooZv.mjs} +2 -2
- package/dist/_chunks/{LanguagesSelector-vu-Lj7L6.mjs → LanguagesSelector-BbrMKwQY.mjs} +3 -3
- package/dist/_chunks/{LanguagesSelector-DsW3aJ7p.js → LanguagesSelector-CC1ecWnc.js} +3 -3
- package/dist/_chunks/{LocalazyApp-BIll8u_G.js → LocalazyApp-D0JGRQeF.js} +87 -10
- package/dist/_chunks/{LocalazyApp-Dxygk1mM.mjs → LocalazyApp-DpFR8p10.mjs} +88 -11
- package/dist/_chunks/{LocalazyContentTransferSetup-BhEjlIgE.js → LocalazyContentTransferSetup-Cr7D-BUi.js} +5 -5
- package/dist/_chunks/{LocalazyContentTransferSetup-Cz88htly.mjs → LocalazyContentTransferSetup-Dael1Q4w.mjs} +5 -5
- package/dist/_chunks/{LocalazyGlobalSettings-B3Z8f4G8.js → LocalazyGlobalSettings-D3nG4zl7.js} +6 -6
- package/dist/_chunks/{LocalazyGlobalSettings-CgOADY93.mjs → LocalazyGlobalSettings-DzBI5M-K.mjs} +6 -6
- package/dist/_chunks/{LocalazyPanel-CQ8-K88T.js → LocalazyPanel-KQPLxTDz.js} +3 -3
- package/dist/_chunks/{LocalazyPanel-BjrSVZpI.mjs → LocalazyPanel-W6j8N1WC.mjs} +3 -3
- package/dist/_chunks/{LocalazyStatusColumn-CA34yhSE.js → LocalazyStatusColumn-B7Q_U2Lu.js} +2 -2
- package/dist/_chunks/{LocalazyStatusColumn-D0b2LCpg.mjs → LocalazyStatusColumn-CrhsCjgp.mjs} +2 -2
- package/dist/_chunks/{RequireLocalazyAuth-DpimzlRh.mjs → RequireLocalazyAuth-BwoGRfJq.mjs} +4 -4
- package/dist/_chunks/{RequireLocalazyAuth-BPsrUlFm.js → RequireLocalazyAuth-D3GeZPDh.js} +4 -4
- package/dist/_chunks/{entry-exclusion-service-nJswJPwF.js → entry-exclusion-service-Bwruvyce.js} +1 -1
- package/dist/_chunks/{entry-exclusion-service-DNJZg3U2.mjs → entry-exclusion-service-D7gaRHPE.mjs} +1 -1
- package/dist/_chunks/{has-model-changed-BnL6D-eR.js → has-model-changed-5IV9WI_-.js} +2 -2
- package/dist/_chunks/{has-model-changed-D6fjlIdc.mjs → has-model-changed-Dp2Vkwjw.mjs} +2 -2
- package/dist/_chunks/{i18n-CAsbU4pi.js → i18n-C_5tJvr0.js} +5 -1
- package/dist/_chunks/{i18n-QelOdIB2.mjs → i18n-o24yXf-j.mjs} +5 -1
- package/dist/_chunks/{index-CHjIMO9T.mjs → index-BjL9XpRh.mjs} +4 -3
- package/dist/_chunks/{index-CPBTdynk.mjs → index-C9hN3KbD.mjs} +8 -8
- package/dist/_chunks/{index-BK7lmZSN.js → index-CTkxoioB.js} +1 -0
- package/dist/_chunks/{index-BXPaiO0d.js → index-jAg6jjCu.js} +8 -8
- package/dist/_chunks/strapi-api-base-CAzGcwF6.mjs +23 -0
- package/dist/_chunks/strapi-api-base-IG3Pe5Sg.js +22 -0
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/modules/@common/api/strapi-api-base.d.ts +19 -4
- package/dist/admin/src/modules/@common/utils/sort-by-model-name.d.ts +1 -1
- package/dist/admin/src/modules/activity-logs/locale/en.d.ts +4 -0
- package/dist/admin/src/modules/activity-logs/services/debug-bundle-service.d.ts +10 -0
- package/dist/server/index.js +510 -5
- package/dist/server/index.mjs +510 -6
- package/dist/server/src/controllers/debug-bundle-controller.d.ts +7 -0
- package/dist/server/src/controllers/index.d.ts +5 -0
- package/dist/server/src/core/index.d.ts +2 -0
- package/dist/server/src/db/model/activity-logs.d.ts +10 -0
- package/dist/server/src/index.d.ts +7 -0
- package/dist/server/src/routes/debug-bundle-routes.d.ts +9 -0
- package/dist/server/src/services/activity-logs-service.d.ts +3 -1
- package/dist/server/src/services/index.d.ts +2 -0
- package/dist/server/src/utils/build-debug-bundle.d.ts +68 -0
- package/dist/server/src/utils/sanitize-debug-bundle.d.ts +25 -0
- package/package.json +2 -2
- package/dist/_chunks/strapi-api-base-DkjMgMHl.js +0 -2425
- package/dist/_chunks/strapi-api-base-GgrMbYak.mjs +0 -2426
package/dist/server/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import require$$0$4 from "http";
|
|
2
|
-
import require$$1$4 from "fs";
|
|
2
|
+
import require$$1$4, { promises } from "fs";
|
|
3
3
|
import require$$1$1 from "zlib";
|
|
4
4
|
import require$$1 from "path";
|
|
5
5
|
import require$$4 from "stream";
|
|
@@ -9,6 +9,7 @@ import require$$0$2 from "crypto";
|
|
|
9
9
|
import require$$0$3 from "events";
|
|
10
10
|
import require$$2 from "timers";
|
|
11
11
|
import require$$8, { WebSocketServer } from "ws";
|
|
12
|
+
import JSZip from "jszip";
|
|
12
13
|
var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
|
|
13
14
|
function getDefaultExportFromCjs(x2) {
|
|
14
15
|
return x2 && x2.__esModule && Object.prototype.hasOwnProperty.call(x2, "default") ? x2["default"] : x2;
|
|
@@ -20519,7 +20520,7 @@ var distExports = dist$1.exports;
|
|
|
20519
20520
|
const io = /* @__PURE__ */ getDefaultExportFromCjs(distExports);
|
|
20520
20521
|
const { Server: Server2, Namespace, Socket: Socket3 } = io;
|
|
20521
20522
|
const name = "@localazy/strapi-plugin";
|
|
20522
|
-
const version = "1.
|
|
20523
|
+
const version = "1.4.0";
|
|
20523
20524
|
const description = "The official Strapi Plugin by Localazy.";
|
|
20524
20525
|
const keywords = [
|
|
20525
20526
|
"strapi",
|
|
@@ -20589,6 +20590,7 @@ const scripts = {
|
|
|
20589
20590
|
prepare: "husky || true"
|
|
20590
20591
|
};
|
|
20591
20592
|
const dependencies = {
|
|
20593
|
+
jszip: "^3.10.1",
|
|
20592
20594
|
shelljs: "^0.8.5",
|
|
20593
20595
|
ws: "^8.18.0"
|
|
20594
20596
|
};
|
|
@@ -20607,7 +20609,6 @@ const devDependencies = {
|
|
|
20607
20609
|
"@types/react-dom": "^19.0.2",
|
|
20608
20610
|
"@typescript-eslint/eslint-plugin": "^8.21.0",
|
|
20609
20611
|
"@typescript-eslint/parser": "^8.21.0",
|
|
20610
|
-
axios: "^1.7.9",
|
|
20611
20612
|
chalk: "^5.4.1",
|
|
20612
20613
|
"conventional-changelog": "^5.1.0",
|
|
20613
20614
|
"conventional-changelog-cli": "^4.1.0",
|
|
@@ -24489,6 +24490,413 @@ const ActivityLogsController = ({ strapi: _strapi }) => ({
|
|
|
24489
24490
|
ctx.body = { success: true };
|
|
24490
24491
|
}
|
|
24491
24492
|
});
|
|
24493
|
+
const URL_SECRET_KEYS = ["token", "secret", "signature", "key", "apikey", "api_key"];
|
|
24494
|
+
const DEBUG_BUNDLE_ENV_ALLOWLIST = [
|
|
24495
|
+
"STRAPI_ADMIN_LOCALAZY_ENV",
|
|
24496
|
+
"STRAPI_ADMIN_BACKEND_URL",
|
|
24497
|
+
"NODE_ENV",
|
|
24498
|
+
"STRAPI_TELEMETRY_DISABLED"
|
|
24499
|
+
];
|
|
24500
|
+
const redactIdentity = (identity2) => {
|
|
24501
|
+
if (!identity2) return null;
|
|
24502
|
+
return {
|
|
24503
|
+
userId: identity2.user?.id ?? "",
|
|
24504
|
+
name: identity2.user?.name ?? "",
|
|
24505
|
+
scope: identity2.scope ?? "",
|
|
24506
|
+
hasAccessToken: Boolean(identity2.accessToken)
|
|
24507
|
+
};
|
|
24508
|
+
};
|
|
24509
|
+
const scrubUrlSecrets = (input) => {
|
|
24510
|
+
if (typeof input !== "string") return input;
|
|
24511
|
+
if (!/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(input) && !input.includes("?")) return input;
|
|
24512
|
+
try {
|
|
24513
|
+
const url2 = new URL(input);
|
|
24514
|
+
let mutated = false;
|
|
24515
|
+
for (const k2 of [...url2.searchParams.keys()]) {
|
|
24516
|
+
if (URL_SECRET_KEYS.includes(k2.toLowerCase())) {
|
|
24517
|
+
url2.searchParams.delete(k2);
|
|
24518
|
+
mutated = true;
|
|
24519
|
+
}
|
|
24520
|
+
}
|
|
24521
|
+
return mutated ? url2.toString() : input;
|
|
24522
|
+
} catch {
|
|
24523
|
+
return input;
|
|
24524
|
+
}
|
|
24525
|
+
};
|
|
24526
|
+
const pickEnvAllowlist = (env) => {
|
|
24527
|
+
const out = {};
|
|
24528
|
+
for (const key of DEBUG_BUNDLE_ENV_ALLOWLIST) {
|
|
24529
|
+
const raw = env[key];
|
|
24530
|
+
const present = raw !== void 0;
|
|
24531
|
+
out[key] = {
|
|
24532
|
+
present,
|
|
24533
|
+
value: present ? raw : null
|
|
24534
|
+
};
|
|
24535
|
+
}
|
|
24536
|
+
return out;
|
|
24537
|
+
};
|
|
24538
|
+
const serializeContentTypeSchema = (contentType) => {
|
|
24539
|
+
if (!contentType || typeof contentType !== "object") return null;
|
|
24540
|
+
const ct = contentType;
|
|
24541
|
+
return {
|
|
24542
|
+
kind: ct.kind,
|
|
24543
|
+
collectionName: ct.collectionName,
|
|
24544
|
+
info: ct.info,
|
|
24545
|
+
options: ct.options,
|
|
24546
|
+
pluginOptions: ct.pluginOptions,
|
|
24547
|
+
attributes: ct.attributes
|
|
24548
|
+
};
|
|
24549
|
+
};
|
|
24550
|
+
const DOCUMENT_INTERNAL_FIELDS = ["createdBy", "updatedBy"];
|
|
24551
|
+
const stripDocumentInternals = (doc) => {
|
|
24552
|
+
if (!doc || typeof doc !== "object") return doc;
|
|
24553
|
+
const clone = { ...doc };
|
|
24554
|
+
for (const field of DOCUMENT_INTERNAL_FIELDS) {
|
|
24555
|
+
delete clone[field];
|
|
24556
|
+
}
|
|
24557
|
+
return clone;
|
|
24558
|
+
};
|
|
24559
|
+
class SessionNotFoundError extends Error {
|
|
24560
|
+
constructor(sessionId) {
|
|
24561
|
+
super(`Session ${sessionId} not found`);
|
|
24562
|
+
this.name = "SessionNotFoundError";
|
|
24563
|
+
}
|
|
24564
|
+
}
|
|
24565
|
+
const DEBUG_BUNDLE_SCHEMA_VERSION = 1;
|
|
24566
|
+
const CAPS = {
|
|
24567
|
+
perEntryBytes: 1 * 1024 * 1024,
|
|
24568
|
+
// 1 MB
|
|
24569
|
+
totalEntries: 100,
|
|
24570
|
+
errorLogBytes: 2 * 1024 * 1024,
|
|
24571
|
+
// 2 MB
|
|
24572
|
+
consoleErrorsLines: 200,
|
|
24573
|
+
browserPayloadBytes: 64 * 1024
|
|
24574
|
+
// 64 KB
|
|
24575
|
+
};
|
|
24576
|
+
const selectAttemptedEntries = (attempted) => {
|
|
24577
|
+
const failedByKey = /* @__PURE__ */ new Map();
|
|
24578
|
+
const successByKey = /* @__PURE__ */ new Map();
|
|
24579
|
+
for (const record of attempted) {
|
|
24580
|
+
const key = `${record.uid}|${record.documentId}|${record.locale}`;
|
|
24581
|
+
const selected = {
|
|
24582
|
+
uid: record.uid,
|
|
24583
|
+
documentId: record.documentId,
|
|
24584
|
+
locale: record.locale,
|
|
24585
|
+
status: record.status,
|
|
24586
|
+
attemptedAt: record.attemptedAt
|
|
24587
|
+
};
|
|
24588
|
+
if (record.status === "failed") {
|
|
24589
|
+
successByKey.delete(key);
|
|
24590
|
+
if (!failedByKey.has(key)) failedByKey.set(key, selected);
|
|
24591
|
+
} else if (!failedByKey.has(key) && !successByKey.has(key)) {
|
|
24592
|
+
successByKey.set(key, selected);
|
|
24593
|
+
}
|
|
24594
|
+
}
|
|
24595
|
+
return [...failedByKey.values(), ...successByKey.values()];
|
|
24596
|
+
};
|
|
24597
|
+
const formatTimestampForFilename = (ms2) => new Date(ms2).toISOString().replace(/[:.]/g, "-");
|
|
24598
|
+
const safeUidForPath = (uid) => uid.replace(/::/g, "--").replace(/\./g, "-");
|
|
24599
|
+
const decodeBrowserPayload = (encoded) => {
|
|
24600
|
+
const markers = [];
|
|
24601
|
+
if (!encoded) return { payload: null, truncationMarkers: markers };
|
|
24602
|
+
try {
|
|
24603
|
+
const raw = Buffer.from(encoded, "base64").toString("utf8");
|
|
24604
|
+
const rawBytes = Buffer.byteLength(raw, "utf8");
|
|
24605
|
+
if (rawBytes > CAPS.browserPayloadBytes) {
|
|
24606
|
+
markers.push({ kind: "browser-payload-truncated", originalSizeBytes: rawBytes });
|
|
24607
|
+
return { payload: null, truncationMarkers: markers };
|
|
24608
|
+
}
|
|
24609
|
+
const parsed = JSON.parse(raw);
|
|
24610
|
+
if (parsed && Array.isArray(parsed.consoleErrors) && parsed.consoleErrors.length > CAPS.consoleErrorsLines) {
|
|
24611
|
+
markers.push({ kind: "console-errors-truncated", originalCount: parsed.consoleErrors.length });
|
|
24612
|
+
parsed.consoleErrors = parsed.consoleErrors.slice(0, CAPS.consoleErrorsLines);
|
|
24613
|
+
}
|
|
24614
|
+
return { payload: parsed, truncationMarkers: markers };
|
|
24615
|
+
} catch {
|
|
24616
|
+
return { payload: null, truncationMarkers: markers };
|
|
24617
|
+
}
|
|
24618
|
+
};
|
|
24619
|
+
const deepScrubUrls = (value) => {
|
|
24620
|
+
if (value == null) return value;
|
|
24621
|
+
if (typeof value === "string") return scrubUrlSecrets(value);
|
|
24622
|
+
if (Array.isArray(value)) return value.map(deepScrubUrls);
|
|
24623
|
+
if (typeof value === "object") {
|
|
24624
|
+
const out = {};
|
|
24625
|
+
for (const [k2, v2] of Object.entries(value)) {
|
|
24626
|
+
out[k2] = deepScrubUrls(v2);
|
|
24627
|
+
}
|
|
24628
|
+
return out;
|
|
24629
|
+
}
|
|
24630
|
+
return value;
|
|
24631
|
+
};
|
|
24632
|
+
const sanitizePluginSettings = (settings) => {
|
|
24633
|
+
const cloned = JSON.parse(JSON.stringify(settings ?? {}));
|
|
24634
|
+
if (cloned.webhookConfig?.url) {
|
|
24635
|
+
cloned.webhookConfig.url = scrubUrlSecrets(cloned.webhookConfig.url);
|
|
24636
|
+
}
|
|
24637
|
+
return cloned;
|
|
24638
|
+
};
|
|
24639
|
+
const sanitizeSession = (session) => {
|
|
24640
|
+
const cloned = JSON.parse(JSON.stringify(session));
|
|
24641
|
+
for (const entry of cloned.entries ?? []) {
|
|
24642
|
+
if (entry.data !== void 0) {
|
|
24643
|
+
entry.data = deepScrubUrls(entry.data);
|
|
24644
|
+
}
|
|
24645
|
+
}
|
|
24646
|
+
return cloned;
|
|
24647
|
+
};
|
|
24648
|
+
const buildErrorLog = (session) => {
|
|
24649
|
+
const lines = [];
|
|
24650
|
+
for (const entry of session.entries ?? []) {
|
|
24651
|
+
const ts = Number.isFinite(entry.timestamp) ? new Date(entry.timestamp).toISOString() : "unknown";
|
|
24652
|
+
lines.push(`${ts} ${entry.message}`);
|
|
24653
|
+
}
|
|
24654
|
+
if (session.status === "failed" && session.summary) {
|
|
24655
|
+
lines.push(`ERROR: ${session.summary}`);
|
|
24656
|
+
}
|
|
24657
|
+
const full = lines.join("\n");
|
|
24658
|
+
const fullBytes = Buffer.byteLength(full, "utf8");
|
|
24659
|
+
if (fullBytes <= CAPS.errorLogBytes) {
|
|
24660
|
+
return { text: full, markers: [] };
|
|
24661
|
+
}
|
|
24662
|
+
const truncated = Buffer.from(full, "utf8").subarray(fullBytes - CAPS.errorLogBytes).toString("utf8");
|
|
24663
|
+
return {
|
|
24664
|
+
text: `...[truncated, kept last ${CAPS.errorLogBytes} bytes]
|
|
24665
|
+
${truncated}`,
|
|
24666
|
+
markers: [{ kind: "error-log-truncated", originalSizeBytes: fullBytes }]
|
|
24667
|
+
};
|
|
24668
|
+
};
|
|
24669
|
+
const readHostPackages = async (strapi2) => {
|
|
24670
|
+
const appRoot = strapi2?.dirs?.app?.root ?? process.cwd();
|
|
24671
|
+
if (!appRoot) return { data: null, reason: "host-app-root-unknown" };
|
|
24672
|
+
try {
|
|
24673
|
+
const raw = await promises.readFile(require$$1.join(appRoot, "package.json"), "utf8");
|
|
24674
|
+
const parsed = JSON.parse(raw);
|
|
24675
|
+
return {
|
|
24676
|
+
data: {
|
|
24677
|
+
name: parsed.name,
|
|
24678
|
+
version: parsed.version,
|
|
24679
|
+
dependencies: parsed.dependencies ?? {},
|
|
24680
|
+
devDependencies: parsed.devDependencies ?? {}
|
|
24681
|
+
}
|
|
24682
|
+
};
|
|
24683
|
+
} catch (err) {
|
|
24684
|
+
return { data: null, reason: err instanceof Error ? err.message : String(err) };
|
|
24685
|
+
}
|
|
24686
|
+
};
|
|
24687
|
+
const buildReadme = ({
|
|
24688
|
+
sessionShortId,
|
|
24689
|
+
sessionId,
|
|
24690
|
+
schemaVersion,
|
|
24691
|
+
hostPackagesSkipped
|
|
24692
|
+
}) => {
|
|
24693
|
+
const lines = [];
|
|
24694
|
+
lines.push(`# Localazy Strapi Plugin — Troubleshooting Bundle`);
|
|
24695
|
+
lines.push("");
|
|
24696
|
+
lines.push(`Generated: ${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
24697
|
+
lines.push(`Session id: ${sessionId}`);
|
|
24698
|
+
lines.push(`Schema version: ${schemaVersion}`);
|
|
24699
|
+
lines.push("");
|
|
24700
|
+
lines.push("## Contents");
|
|
24701
|
+
lines.push("");
|
|
24702
|
+
lines.push("- `meta.json` — schema version, session metadata.");
|
|
24703
|
+
lines.push("- `versions.json` — plugin version, Strapi version, Node version, platform/arch.");
|
|
24704
|
+
lines.push("- `env.json` — allow-listed environment variables only.");
|
|
24705
|
+
lines.push("- `browser.json` — user agent, language, viewport, console errors (from the admin UI).");
|
|
24706
|
+
lines.push("- `session.json` — full activity-log session record (URLs scrubbed of secret query keys).");
|
|
24707
|
+
lines.push("- `error.log` — chronological text log of session entries.");
|
|
24708
|
+
lines.push("- `plugin-settings.json` — full plugin settings (webhook URL secrets scrubbed).");
|
|
24709
|
+
lines.push("- `content-transfer-setup.json` — content-transfer setup record.");
|
|
24710
|
+
if (hostPackagesSkipped) {
|
|
24711
|
+
lines.push("- `host-packages.json` — NOT INCLUDED (could not be read; see `bundle-truncated.json`).");
|
|
24712
|
+
} else {
|
|
24713
|
+
lines.push("- `host-packages.json` — host project's package.json (deps + devDeps only).");
|
|
24714
|
+
}
|
|
24715
|
+
lines.push("- `content-types/` — schema.json per touched content-type UID.");
|
|
24716
|
+
lines.push("- `entries/<uid>/<documentId>--<locale>.json` — per-entry payload from `strapi.documents().findOne()`.");
|
|
24717
|
+
lines.push("- `bundle-truncated.json` — present only if any per-section cap was exceeded.");
|
|
24718
|
+
lines.push("");
|
|
24719
|
+
lines.push("## Reproducing locally");
|
|
24720
|
+
lines.push("");
|
|
24721
|
+
lines.push("1. `unzip` the bundle.");
|
|
24722
|
+
lines.push("2. Recreate the content types from `content-types/*.schema.json` in your Strapi project.");
|
|
24723
|
+
lines.push("3. Import the entries via the Document Service using `entries/<uid>/*.json`.");
|
|
24724
|
+
lines.push("4. Apply `plugin-settings.json` and `content-transfer-setup.json` via the plugin admin UI.");
|
|
24725
|
+
lines.push("5. Trigger the same upload/download/webhook with the same locale set.");
|
|
24726
|
+
lines.push("6. Compare the failure against `error.log` and `session.json`.");
|
|
24727
|
+
lines.push("");
|
|
24728
|
+
lines.push(`Bundle short id: ${sessionShortId}`);
|
|
24729
|
+
return lines.join("\n");
|
|
24730
|
+
};
|
|
24731
|
+
const buildDebugBundle = async ({
|
|
24732
|
+
strapi: strapi2,
|
|
24733
|
+
sessionId,
|
|
24734
|
+
browserPayloadEncoded
|
|
24735
|
+
}) => {
|
|
24736
|
+
const zip = new JSZip();
|
|
24737
|
+
const truncationMarkers = [];
|
|
24738
|
+
const pluginName = "localazy";
|
|
24739
|
+
const activityLogsService = strapi2.plugin(pluginName).service("ActivityLogsService");
|
|
24740
|
+
const pluginSettingsService = strapi2.plugin(pluginName).service("PluginSettingsService");
|
|
24741
|
+
const strapiService = strapi2.plugin(pluginName).service("StrapiService");
|
|
24742
|
+
const localazyUserService = strapi2.plugin(pluginName).service("LocalazyUserService");
|
|
24743
|
+
const session = await activityLogsService.getSession(sessionId);
|
|
24744
|
+
if (!session) {
|
|
24745
|
+
throw new SessionNotFoundError(sessionId);
|
|
24746
|
+
}
|
|
24747
|
+
const sessionShortId = session.id.slice(0, 8);
|
|
24748
|
+
const pluginSettingsRaw = await pluginSettingsService.getPluginSettings();
|
|
24749
|
+
const contentTransferSetup = await pluginSettingsService.getContentTransferSetup();
|
|
24750
|
+
const identity2 = await localazyUserService.getUser();
|
|
24751
|
+
const redactedIdentity = redactIdentity(identity2);
|
|
24752
|
+
const pluginVersion = await strapiService.getPluginVersion();
|
|
24753
|
+
const strapiVersion = strapiService.getStrapiVersion();
|
|
24754
|
+
zip.file(
|
|
24755
|
+
"meta.json",
|
|
24756
|
+
JSON.stringify(
|
|
24757
|
+
{
|
|
24758
|
+
schemaVersion: DEBUG_BUNDLE_SCHEMA_VERSION,
|
|
24759
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
24760
|
+
sessionId: session.id,
|
|
24761
|
+
sessionShortId,
|
|
24762
|
+
eventType: session.eventType,
|
|
24763
|
+
status: session.status,
|
|
24764
|
+
startedAt: session.startedAt,
|
|
24765
|
+
finishedAt: session.finishedAt ?? null,
|
|
24766
|
+
initiatedBy: session.initiatedBy,
|
|
24767
|
+
identity: redactedIdentity
|
|
24768
|
+
},
|
|
24769
|
+
null,
|
|
24770
|
+
2
|
|
24771
|
+
)
|
|
24772
|
+
);
|
|
24773
|
+
zip.file(
|
|
24774
|
+
"versions.json",
|
|
24775
|
+
JSON.stringify(
|
|
24776
|
+
{
|
|
24777
|
+
plugin: { name: "@localazy/strapi-plugin", version: pluginVersion },
|
|
24778
|
+
strapi: { version: strapiVersion },
|
|
24779
|
+
node: process.version,
|
|
24780
|
+
platform: process.platform,
|
|
24781
|
+
arch: process.arch
|
|
24782
|
+
},
|
|
24783
|
+
null,
|
|
24784
|
+
2
|
|
24785
|
+
)
|
|
24786
|
+
);
|
|
24787
|
+
const envSnapshot = pickEnvAllowlist(process.env);
|
|
24788
|
+
zip.file(
|
|
24789
|
+
"env.json",
|
|
24790
|
+
JSON.stringify(
|
|
24791
|
+
{
|
|
24792
|
+
allowlist: [...DEBUG_BUNDLE_ENV_ALLOWLIST],
|
|
24793
|
+
values: envSnapshot
|
|
24794
|
+
},
|
|
24795
|
+
null,
|
|
24796
|
+
2
|
|
24797
|
+
)
|
|
24798
|
+
);
|
|
24799
|
+
const { payload: browserPayload, truncationMarkers: browserMarkers } = decodeBrowserPayload(browserPayloadEncoded);
|
|
24800
|
+
truncationMarkers.push(...browserMarkers);
|
|
24801
|
+
zip.file("browser.json", JSON.stringify(browserPayload ? browserPayload : { captured: false }, null, 2));
|
|
24802
|
+
zip.file("session.json", JSON.stringify(sanitizeSession(session), null, 2));
|
|
24803
|
+
const { text: errorLogText, markers: errorLogMarkers } = buildErrorLog(session);
|
|
24804
|
+
truncationMarkers.push(...errorLogMarkers);
|
|
24805
|
+
zip.file("error.log", errorLogText);
|
|
24806
|
+
zip.file("plugin-settings.json", JSON.stringify(sanitizePluginSettings(pluginSettingsRaw), null, 2));
|
|
24807
|
+
zip.file("content-transfer-setup.json", JSON.stringify(contentTransferSetup, null, 2));
|
|
24808
|
+
const hostPackages = await readHostPackages(strapi2);
|
|
24809
|
+
if (hostPackages.data) {
|
|
24810
|
+
zip.file("host-packages.json", JSON.stringify(hostPackages.data, null, 2));
|
|
24811
|
+
}
|
|
24812
|
+
if (session.attemptedEntries === void 0) {
|
|
24813
|
+
truncationMarkers.push({ kind: "attempted-entries-missing-legacy-session" });
|
|
24814
|
+
}
|
|
24815
|
+
const selected = selectAttemptedEntries(session.attemptedEntries ?? []);
|
|
24816
|
+
const kept = selected.slice(0, CAPS.totalEntries);
|
|
24817
|
+
const skipped = selected.slice(CAPS.totalEntries);
|
|
24818
|
+
if (skipped.length > 0) {
|
|
24819
|
+
truncationMarkers.push({
|
|
24820
|
+
kind: "entries-skipped",
|
|
24821
|
+
tuples: skipped.map(({ uid, documentId, locale }) => ({ uid, documentId, locale }))
|
|
24822
|
+
});
|
|
24823
|
+
}
|
|
24824
|
+
const uniqueUids = [...new Set(kept.map((t3) => t3.uid))];
|
|
24825
|
+
for (const uid of uniqueUids) {
|
|
24826
|
+
const schema = serializeContentTypeSchema(strapi2.contentTypes?.[uid]);
|
|
24827
|
+
if (schema) {
|
|
24828
|
+
zip.file(`content-types/${safeUidForPath(uid)}.schema.json`, JSON.stringify(schema, null, 2));
|
|
24829
|
+
}
|
|
24830
|
+
}
|
|
24831
|
+
for (const tuple of kept) {
|
|
24832
|
+
let documentJson = null;
|
|
24833
|
+
try {
|
|
24834
|
+
const doc = await strapi2.documents(tuple.uid).findOne({ documentId: tuple.documentId, locale: tuple.locale, populate: "*" });
|
|
24835
|
+
documentJson = doc ? stripDocumentInternals(doc) : { __not_found: true, attemptedAt: tuple.attemptedAt };
|
|
24836
|
+
} catch (err) {
|
|
24837
|
+
documentJson = { __error: err instanceof Error ? err.message : String(err) };
|
|
24838
|
+
}
|
|
24839
|
+
const serialised = JSON.stringify(documentJson, null, 2);
|
|
24840
|
+
const sizeBytes = Buffer.byteLength(serialised, "utf8");
|
|
24841
|
+
let body;
|
|
24842
|
+
if (sizeBytes > CAPS.perEntryBytes) {
|
|
24843
|
+
truncationMarkers.push({
|
|
24844
|
+
kind: "entry-too-large",
|
|
24845
|
+
uid: tuple.uid,
|
|
24846
|
+
documentId: tuple.documentId,
|
|
24847
|
+
locale: tuple.locale,
|
|
24848
|
+
originalSizeBytes: sizeBytes
|
|
24849
|
+
});
|
|
24850
|
+
body = JSON.stringify({ __truncated: true, originalSizeBytes: sizeBytes }, null, 2);
|
|
24851
|
+
} else {
|
|
24852
|
+
body = serialised;
|
|
24853
|
+
}
|
|
24854
|
+
const safeDocId = tuple.documentId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
24855
|
+
zip.file(`entries/${safeUidForPath(tuple.uid)}/${safeDocId}--${tuple.locale}.json`, body);
|
|
24856
|
+
}
|
|
24857
|
+
zip.file(
|
|
24858
|
+
"README.md",
|
|
24859
|
+
buildReadme({
|
|
24860
|
+
sessionShortId,
|
|
24861
|
+
sessionId: session.id,
|
|
24862
|
+
schemaVersion: DEBUG_BUNDLE_SCHEMA_VERSION,
|
|
24863
|
+
hostPackagesSkipped: !hostPackages.data
|
|
24864
|
+
})
|
|
24865
|
+
);
|
|
24866
|
+
if (truncationMarkers.length > 0 || !hostPackages.data) {
|
|
24867
|
+
const marker = {
|
|
24868
|
+
schemaVersion: DEBUG_BUNDLE_SCHEMA_VERSION,
|
|
24869
|
+
markers: truncationMarkers,
|
|
24870
|
+
hostPackagesSkipped: hostPackages.data ? null : hostPackages.reason ?? "unknown"
|
|
24871
|
+
};
|
|
24872
|
+
zip.file("bundle-truncated.json", JSON.stringify(marker, null, 2));
|
|
24873
|
+
}
|
|
24874
|
+
const zipBuffer = await zip.generateAsync({ type: "nodebuffer", compression: "DEFLATE" });
|
|
24875
|
+
const filename = `localazy-debug-bundle-${sessionShortId}-${formatTimestampForFilename(Date.now())}.zip`;
|
|
24876
|
+
return { zipBuffer, filename };
|
|
24877
|
+
};
|
|
24878
|
+
const DebugBundleController = ({ strapi: strapi2 }) => ({
|
|
24879
|
+
async getBundle(ctx) {
|
|
24880
|
+
const { sessionId } = ctx.params;
|
|
24881
|
+
const browserPayloadEncoded = typeof ctx.query.browser === "string" ? ctx.query.browser : null;
|
|
24882
|
+
try {
|
|
24883
|
+
const { zipBuffer, filename } = await buildDebugBundle({
|
|
24884
|
+
strapi: strapi2,
|
|
24885
|
+
sessionId,
|
|
24886
|
+
browserPayloadEncoded
|
|
24887
|
+
});
|
|
24888
|
+
ctx.type = "application/zip";
|
|
24889
|
+
ctx.set("Content-Disposition", `attachment; filename="${filename}"`);
|
|
24890
|
+
ctx.body = zipBuffer;
|
|
24891
|
+
} catch (err) {
|
|
24892
|
+
if (err instanceof SessionNotFoundError) {
|
|
24893
|
+
return ctx.notFound("Session not found");
|
|
24894
|
+
}
|
|
24895
|
+
strapi2.log.error(`[localazy] failed to build debug bundle: ${err instanceof Error ? err.message : err}`);
|
|
24896
|
+
throw err;
|
|
24897
|
+
}
|
|
24898
|
+
}
|
|
24899
|
+
});
|
|
24492
24900
|
const controllers = {
|
|
24493
24901
|
LocalazyUserController,
|
|
24494
24902
|
LocalazyAuthController,
|
|
@@ -24497,7 +24905,8 @@ const controllers = {
|
|
|
24497
24905
|
PluginSettingsController,
|
|
24498
24906
|
LocalazyTransferController,
|
|
24499
24907
|
EntryExclusionController,
|
|
24500
|
-
ActivityLogsController
|
|
24908
|
+
ActivityLogsController,
|
|
24909
|
+
DebugBundleController
|
|
24501
24910
|
};
|
|
24502
24911
|
const verifyWebhook = (config2, { strapi: strapi2 }) => {
|
|
24503
24912
|
return async (ctx, next) => {
|
|
@@ -24808,6 +25217,16 @@ const ActivityLogsRoutes = [
|
|
|
24808
25217
|
}
|
|
24809
25218
|
}
|
|
24810
25219
|
];
|
|
25220
|
+
const DebugBundleRoutes = [
|
|
25221
|
+
{
|
|
25222
|
+
method: "GET",
|
|
25223
|
+
path: "/activity-logs/:sessionId/bundle",
|
|
25224
|
+
handler: "DebugBundleController.getBundle",
|
|
25225
|
+
config: {
|
|
25226
|
+
policies: []
|
|
25227
|
+
}
|
|
25228
|
+
}
|
|
25229
|
+
];
|
|
24811
25230
|
const routes = {
|
|
24812
25231
|
"content-api": {
|
|
24813
25232
|
routes: [...StrapiRoutes]
|
|
@@ -24822,7 +25241,8 @@ const routes = {
|
|
|
24822
25241
|
...LocalazyTransferRoutes,
|
|
24823
25242
|
...LocalazyProjectRoutes,
|
|
24824
25243
|
...EntryExclusionRoutes,
|
|
24825
|
-
...ActivityLogsRoutes
|
|
25244
|
+
...ActivityLogsRoutes,
|
|
25245
|
+
...DebugBundleRoutes
|
|
24826
25246
|
]
|
|
24827
25247
|
},
|
|
24828
25248
|
LocalazyPublicTransferRoutes: {
|
|
@@ -25101,6 +25521,8 @@ const LocalazyTransferUploadService = ({ strapi: strapi2 }) => ({
|
|
|
25101
25521
|
const { setup: setup2 } = contentTransferSetup;
|
|
25102
25522
|
const collectionsNames = getCollectionsNames(setup2);
|
|
25103
25523
|
const models = await StrapiService2.getModels();
|
|
25524
|
+
const strapiDefaultLocaleCode = await StrapiI18nService2.getDefaultLocaleCode();
|
|
25525
|
+
const attemptedTuples = [];
|
|
25104
25526
|
let pickedFlattenStrapiContent = {};
|
|
25105
25527
|
for (const collectionName of collectionsNames) {
|
|
25106
25528
|
const currentModel = models.find((model) => model.collectionName === collectionName);
|
|
@@ -25163,6 +25585,15 @@ const LocalazyTransferUploadService = ({ strapi: strapi2 }) => ({
|
|
|
25163
25585
|
});
|
|
25164
25586
|
await activityLogsService.addEntry(sessionId, message);
|
|
25165
25587
|
strapi2.log.info(message);
|
|
25588
|
+
if (strapiDefaultLocaleCode) {
|
|
25589
|
+
for (const entry of entries) {
|
|
25590
|
+
attemptedTuples.push({
|
|
25591
|
+
uid: modelUid,
|
|
25592
|
+
documentId: entry.documentId,
|
|
25593
|
+
locale: strapiDefaultLocaleCode
|
|
25594
|
+
});
|
|
25595
|
+
}
|
|
25596
|
+
}
|
|
25166
25597
|
entries = omitDeep(entries, ["locale", "createdAt", "updatedAt", "publishedAt"]);
|
|
25167
25598
|
entries.forEach((entry) => {
|
|
25168
25599
|
const flatten = flattenObject({
|
|
@@ -25180,7 +25611,6 @@ const LocalazyTransferUploadService = ({ strapi: strapi2 }) => ({
|
|
|
25180
25611
|
...characterLimitsMetadata
|
|
25181
25612
|
};
|
|
25182
25613
|
}
|
|
25183
|
-
const strapiDefaultLocaleCode = await StrapiI18nService2.getDefaultLocaleCode();
|
|
25184
25614
|
const localazyLocaleCode = strapiDefaultLocaleCode ? isoStrapiToLocalazy(strapiDefaultLocaleCode) : config.default.LOCALAZY_DEFAULT_LOCALE;
|
|
25185
25615
|
const importFile = LocalazyUploadService2.createImportFileRepresentation(
|
|
25186
25616
|
localazyLocaleCode,
|
|
@@ -25202,6 +25632,10 @@ const LocalazyTransferUploadService = ({ strapi: strapi2 }) => ({
|
|
|
25202
25632
|
await activityLogsService.addEntry(sessionId, "Uploading collections to Localazy...");
|
|
25203
25633
|
try {
|
|
25204
25634
|
await LocalazyUploadService2.upload(importFile, uploadConfig);
|
|
25635
|
+
await activityLogsService.recordAttemptedEntries(
|
|
25636
|
+
sessionId,
|
|
25637
|
+
attemptedTuples.map((t3) => ({ ...t3, status: "success" }))
|
|
25638
|
+
);
|
|
25205
25639
|
} catch (error) {
|
|
25206
25640
|
success = false;
|
|
25207
25641
|
const errorMessage = `Upload to Localazy failed: ${error instanceof Error ? error.message : String(error)}`;
|
|
@@ -25211,6 +25645,10 @@ const LocalazyTransferUploadService = ({ strapi: strapi2 }) => ({
|
|
|
25211
25645
|
message: errorMessage
|
|
25212
25646
|
});
|
|
25213
25647
|
await activityLogsService.addEntry(sessionId, errorMessage);
|
|
25648
|
+
await activityLogsService.recordAttemptedEntries(
|
|
25649
|
+
sessionId,
|
|
25650
|
+
attemptedTuples.map((t3) => ({ ...t3, status: "failed", errorMessage }))
|
|
25651
|
+
);
|
|
25214
25652
|
await activityLogsService.finishSession(sessionId, "failed", errorMessage);
|
|
25215
25653
|
console.timeEnd("upload");
|
|
25216
25654
|
return;
|
|
@@ -25935,6 +26373,12 @@ const LocalazyTransferDownloadService = ({ strapi: strapi2 }) => ({
|
|
|
25935
26373
|
message
|
|
25936
26374
|
});
|
|
25937
26375
|
await activityLogsService.addEntry(sessionId, message);
|
|
26376
|
+
await activityLogsService.recordAttemptedEntry(sessionId, {
|
|
26377
|
+
uid,
|
|
26378
|
+
documentId,
|
|
26379
|
+
locale: isoStrapi,
|
|
26380
|
+
status: "success"
|
|
26381
|
+
});
|
|
25938
26382
|
await markKeysProcessed(sourceKeys);
|
|
25939
26383
|
} catch (e2) {
|
|
25940
26384
|
success = false;
|
|
@@ -25951,6 +26395,13 @@ const LocalazyTransferDownloadService = ({ strapi: strapi2 }) => ({
|
|
|
25951
26395
|
sessionId,
|
|
25952
26396
|
`Failed to create ${uid} [${documentId}] in ${isoStrapi}: ${e2.message}`
|
|
25953
26397
|
);
|
|
26398
|
+
await activityLogsService.recordAttemptedEntry(sessionId, {
|
|
26399
|
+
uid,
|
|
26400
|
+
documentId,
|
|
26401
|
+
locale: isoStrapi,
|
|
26402
|
+
status: "failed",
|
|
26403
|
+
errorMessage: e2.message
|
|
26404
|
+
});
|
|
25954
26405
|
}
|
|
25955
26406
|
} else {
|
|
25956
26407
|
try {
|
|
@@ -25969,6 +26420,12 @@ const LocalazyTransferDownloadService = ({ strapi: strapi2 }) => ({
|
|
|
25969
26420
|
message
|
|
25970
26421
|
});
|
|
25971
26422
|
await activityLogsService.addEntry(sessionId, message);
|
|
26423
|
+
await activityLogsService.recordAttemptedEntry(sessionId, {
|
|
26424
|
+
uid,
|
|
26425
|
+
documentId,
|
|
26426
|
+
locale: isoStrapi,
|
|
26427
|
+
status: "success"
|
|
26428
|
+
});
|
|
25972
26429
|
await markKeysProcessed(sourceKeys);
|
|
25973
26430
|
} catch (e2) {
|
|
25974
26431
|
success = false;
|
|
@@ -25985,6 +26442,13 @@ const LocalazyTransferDownloadService = ({ strapi: strapi2 }) => ({
|
|
|
25985
26442
|
sessionId,
|
|
25986
26443
|
`Failed to update ${uid} [${documentId}] in ${isoStrapi}: ${e2.message}`
|
|
25987
26444
|
);
|
|
26445
|
+
await activityLogsService.recordAttemptedEntry(sessionId, {
|
|
26446
|
+
uid,
|
|
26447
|
+
documentId,
|
|
26448
|
+
locale: isoStrapi,
|
|
26449
|
+
status: "failed",
|
|
26450
|
+
errorMessage: e2.message
|
|
26451
|
+
});
|
|
25988
26452
|
}
|
|
25989
26453
|
}
|
|
25990
26454
|
} catch (e2) {
|
|
@@ -25997,6 +26461,13 @@ const LocalazyTransferDownloadService = ({ strapi: strapi2 }) => ({
|
|
|
25997
26461
|
sessionId,
|
|
25998
26462
|
`Error processing ${uid} [${documentId}] in ${isoStrapi}: ${e2.message}`
|
|
25999
26463
|
);
|
|
26464
|
+
await activityLogsService.recordAttemptedEntry(sessionId, {
|
|
26465
|
+
uid,
|
|
26466
|
+
documentId,
|
|
26467
|
+
locale: isoStrapi,
|
|
26468
|
+
status: "failed",
|
|
26469
|
+
errorMessage: e2.message
|
|
26470
|
+
});
|
|
26000
26471
|
}
|
|
26001
26472
|
}
|
|
26002
26473
|
}
|
|
@@ -26747,6 +27218,7 @@ const emptyActivityLogs = {
|
|
|
26747
27218
|
sessions: []
|
|
26748
27219
|
};
|
|
26749
27220
|
const ONE_YEAR_MS = 365 * 24 * 60 * 60 * 1e3;
|
|
27221
|
+
const ATTEMPTED_ENTRIES_CAP = 5e3;
|
|
26750
27222
|
let writeLock = Promise.resolve();
|
|
26751
27223
|
const withLock = async (fn) => {
|
|
26752
27224
|
let release;
|
|
@@ -26811,6 +27283,38 @@ const ActivityLogsService = ({ strapi: strapi2 }) => ({
|
|
|
26811
27283
|
await this.saveActivityLogs(logs);
|
|
26812
27284
|
});
|
|
26813
27285
|
},
|
|
27286
|
+
async recordAttemptedEntry(sessionId, entry) {
|
|
27287
|
+
return this.recordAttemptedEntries(sessionId, [entry]);
|
|
27288
|
+
},
|
|
27289
|
+
async recordAttemptedEntries(sessionId, entries) {
|
|
27290
|
+
if (!entries.length) {
|
|
27291
|
+
return;
|
|
27292
|
+
}
|
|
27293
|
+
return withLock(async () => {
|
|
27294
|
+
const logs = await this.getActivityLogs();
|
|
27295
|
+
const session = logs.sessions.find((s2) => s2.id === sessionId);
|
|
27296
|
+
if (!session) {
|
|
27297
|
+
return;
|
|
27298
|
+
}
|
|
27299
|
+
if (!session.attemptedEntries) {
|
|
27300
|
+
session.attemptedEntries = [];
|
|
27301
|
+
}
|
|
27302
|
+
const now = Date.now();
|
|
27303
|
+
const wasAtCap = session.attemptedEntries.length >= ATTEMPTED_ENTRIES_CAP;
|
|
27304
|
+
const remaining = Math.max(0, ATTEMPTED_ENTRIES_CAP - session.attemptedEntries.length);
|
|
27305
|
+
const accepted = entries.slice(0, remaining);
|
|
27306
|
+
const dropped = entries.length - accepted.length;
|
|
27307
|
+
for (const entry of accepted) {
|
|
27308
|
+
session.attemptedEntries.push({ ...entry, attemptedAt: now });
|
|
27309
|
+
}
|
|
27310
|
+
if (dropped > 0 && !wasAtCap) {
|
|
27311
|
+
strapi2.log.warn(
|
|
27312
|
+
`[localazy] attemptedEntries cap (${ATTEMPTED_ENTRIES_CAP}) reached for session ${sessionId}; ${dropped} record(s) dropped.`
|
|
27313
|
+
);
|
|
27314
|
+
}
|
|
27315
|
+
await this.saveActivityLogs(logs);
|
|
27316
|
+
});
|
|
27317
|
+
},
|
|
26814
27318
|
async finishSession(sessionId, status, summary) {
|
|
26815
27319
|
return withLock(async () => {
|
|
26816
27320
|
const logs = await this.getActivityLogs();
|
|
@@ -58,5 +58,10 @@ declare const _default: {
|
|
|
58
58
|
exportSessions(ctx: any): Promise<void>;
|
|
59
59
|
clearSessions(ctx: any): Promise<void>;
|
|
60
60
|
};
|
|
61
|
+
DebugBundleController: ({ strapi }: {
|
|
62
|
+
strapi: import("@strapi/types/dist/core").Strapi;
|
|
63
|
+
}) => {
|
|
64
|
+
getBundle(ctx: any): Promise<any>;
|
|
65
|
+
};
|
|
61
66
|
};
|
|
62
67
|
export default _default;
|
|
@@ -86,6 +86,8 @@ export declare const getActivityLogsService: () => {
|
|
|
86
86
|
saveActivityLogs(logs: import("../db/model/activity-logs").ActivityLogs): Promise<void>;
|
|
87
87
|
startSession(eventType: "upload" | "download" | "webhook", initiatedBy: string): Promise<string>;
|
|
88
88
|
addEntry(sessionId: string, message: string, data?: any): Promise<void>;
|
|
89
|
+
recordAttemptedEntry(sessionId: string, entry: Omit<import("../db/model/activity-logs").AttemptedEntry, "attemptedAt">): Promise<void>;
|
|
90
|
+
recordAttemptedEntries(sessionId: string, entries: Omit<import("../db/model/activity-logs").AttemptedEntry, "attemptedAt">[]): Promise<void>;
|
|
89
91
|
finishSession(sessionId: string, status: "completed" | "failed", summary: string): Promise<void>;
|
|
90
92
|
getSessions(eventType?: "upload" | "download" | "webhook"): Promise<import("../db/model/activity-logs").ActivityLogSession[]>;
|
|
91
93
|
getAllSessionsWithEntries(): Promise<import("../db/model/activity-logs").ActivityLogSession[]>;
|