@infuro/cms-core 1.0.60 → 1.0.61
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/admin.cjs +579 -47
- package/dist/admin.js +580 -48
- package/dist/api.cjs +33 -33
- package/dist/api.js +1 -1
- package/dist/{chunk-BSLNXKV2.cjs → chunk-CNAHVRRU.cjs} +251 -39
- package/dist/{chunk-JAEUYYGA.js → chunk-UHT4INVW.js} +251 -39
- package/dist/index.cjs +489 -246
- package/dist/index.js +277 -34
- package/package.json +1 -1
|
@@ -3846,14 +3846,14 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
3846
3846
|
if (Number.isFinite(n)) productWhere[key] = n;
|
|
3847
3847
|
}
|
|
3848
3848
|
}
|
|
3849
|
-
const
|
|
3850
|
-
if (
|
|
3851
|
-
const ids =
|
|
3849
|
+
const idsParam2 = searchParams.get("ids")?.trim();
|
|
3850
|
+
if (idsParam2) {
|
|
3851
|
+
const ids = idsParam2.split(",").map((s) => Number(s.trim())).filter((n) => Number.isFinite(n) && n > 0);
|
|
3852
3852
|
productWhere.id = ids.length > 0 ? In(ids) : -1;
|
|
3853
3853
|
} else {
|
|
3854
|
-
const
|
|
3855
|
-
if (
|
|
3856
|
-
const excludeIds =
|
|
3854
|
+
const excludeIdsParam2 = searchParams.get("excludeIds")?.trim();
|
|
3855
|
+
if (excludeIdsParam2) {
|
|
3856
|
+
const excludeIds = excludeIdsParam2.split(",").map((s) => Number(s.trim())).filter((n) => Number.isFinite(n) && n > 0);
|
|
3857
3857
|
if (excludeIds.length > 0) productWhere.id = Not(In(excludeIds));
|
|
3858
3858
|
}
|
|
3859
3859
|
}
|
|
@@ -4130,6 +4130,24 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
4130
4130
|
}
|
|
4131
4131
|
}
|
|
4132
4132
|
where = mergeDeletedFalseWhere(repo, where);
|
|
4133
|
+
const idsParam = searchParams.get("ids")?.trim();
|
|
4134
|
+
if (idsParam && columnNames.has("id")) {
|
|
4135
|
+
const idList = idsParam.split(",").map((s) => Number(s.trim())).filter((n) => Number.isFinite(n) && n > 0);
|
|
4136
|
+
if (idList.length > 0) {
|
|
4137
|
+
where = mergeListWhereAnd(where, {
|
|
4138
|
+
id: In(idList)
|
|
4139
|
+
});
|
|
4140
|
+
}
|
|
4141
|
+
}
|
|
4142
|
+
const excludeIdsParam = searchParams.get("excludeIds")?.trim();
|
|
4143
|
+
if (excludeIdsParam && columnNames.has("id")) {
|
|
4144
|
+
const excludeIdList = excludeIdsParam.split(",").map((s) => Number(s.trim())).filter((n) => Number.isFinite(n) && n > 0);
|
|
4145
|
+
if (excludeIdList.length > 0) {
|
|
4146
|
+
where = mergeListWhereAnd(where, {
|
|
4147
|
+
id: Not(In(excludeIdList))
|
|
4148
|
+
});
|
|
4149
|
+
}
|
|
4150
|
+
}
|
|
4133
4151
|
if (resourceUsesVendorScope(resource)) {
|
|
4134
4152
|
const scope = await resolveScope();
|
|
4135
4153
|
const catalogFlags = await getVendorCatalogCreateFlags(dataSource);
|
|
@@ -8810,25 +8828,79 @@ function createUploadHandler(config) {
|
|
|
8810
8828
|
"application/x-zip-compressed"
|
|
8811
8829
|
];
|
|
8812
8830
|
return /* @__PURE__ */ __name(async function POST(req) {
|
|
8831
|
+
const reqId = `req-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
8832
|
+
console.info("[upload] POST /api/upload start", {
|
|
8833
|
+
reqId,
|
|
8834
|
+
method: req.method,
|
|
8835
|
+
contentType: req.headers.get("content-type"),
|
|
8836
|
+
contentLength: req.headers.get("content-length"),
|
|
8837
|
+
hasStorageConfig: storage != null
|
|
8838
|
+
});
|
|
8813
8839
|
const authErr = await requireAuth(req);
|
|
8814
|
-
if (authErr)
|
|
8840
|
+
if (authErr) {
|
|
8841
|
+
console.error("[upload] auth failed", {
|
|
8842
|
+
reqId,
|
|
8843
|
+
status: authErr.status
|
|
8844
|
+
});
|
|
8845
|
+
return authErr;
|
|
8846
|
+
}
|
|
8847
|
+
console.info("[upload] auth ok", {
|
|
8848
|
+
reqId
|
|
8849
|
+
});
|
|
8815
8850
|
if (requireEntityPermission) {
|
|
8816
8851
|
const pe = await requireEntityPermission(req, "upload", "create");
|
|
8817
|
-
if (pe)
|
|
8852
|
+
if (pe) {
|
|
8853
|
+
console.error("[upload] permission denied", {
|
|
8854
|
+
reqId,
|
|
8855
|
+
status: pe.status
|
|
8856
|
+
});
|
|
8857
|
+
return pe;
|
|
8858
|
+
}
|
|
8859
|
+
console.info("[upload] permission ok", {
|
|
8860
|
+
reqId,
|
|
8861
|
+
entity: "upload",
|
|
8862
|
+
action: "create"
|
|
8863
|
+
});
|
|
8818
8864
|
}
|
|
8819
8865
|
try {
|
|
8866
|
+
console.info("[upload] parsing formData", {
|
|
8867
|
+
reqId
|
|
8868
|
+
});
|
|
8820
8869
|
const formData = await req.formData();
|
|
8821
8870
|
const file = formData.get("file");
|
|
8822
|
-
|
|
8823
|
-
|
|
8824
|
-
|
|
8825
|
-
|
|
8826
|
-
|
|
8827
|
-
|
|
8828
|
-
|
|
8829
|
-
|
|
8830
|
-
|
|
8871
|
+
console.info("[upload] formData parsed", {
|
|
8872
|
+
reqId,
|
|
8873
|
+
hasFile: Boolean(file),
|
|
8874
|
+
fileName: file?.name ?? null,
|
|
8875
|
+
fileType: file?.type ?? null,
|
|
8876
|
+
fileSize: file?.size ?? null,
|
|
8877
|
+
formKeys: [
|
|
8878
|
+
...formData.keys()
|
|
8879
|
+
]
|
|
8831
8880
|
});
|
|
8881
|
+
if (!file) {
|
|
8882
|
+
console.error("[upload] no file in formData", {
|
|
8883
|
+
reqId
|
|
8884
|
+
});
|
|
8885
|
+
return json({
|
|
8886
|
+
error: "No file uploaded"
|
|
8887
|
+
}, {
|
|
8888
|
+
status: 400
|
|
8889
|
+
});
|
|
8890
|
+
}
|
|
8891
|
+
if (!allowed.includes(file.type)) {
|
|
8892
|
+
console.error("[upload] file type not allowed", {
|
|
8893
|
+
reqId,
|
|
8894
|
+
fileType: file.type,
|
|
8895
|
+
fileName: file.name,
|
|
8896
|
+
allowed
|
|
8897
|
+
});
|
|
8898
|
+
return json({
|
|
8899
|
+
error: "File type not allowed"
|
|
8900
|
+
}, {
|
|
8901
|
+
status: 400
|
|
8902
|
+
});
|
|
8903
|
+
}
|
|
8832
8904
|
const defaultMax = 10 * 1024 * 1024;
|
|
8833
8905
|
const maxZipBytes = 80 * 1024 * 1024;
|
|
8834
8906
|
const maxVideoBytes = 100 * 1024 * 1024;
|
|
@@ -8836,25 +8908,51 @@ function createUploadHandler(config) {
|
|
|
8836
8908
|
const isZip = file.type === "application/zip" || file.type === "application/x-zip-compressed";
|
|
8837
8909
|
const isVideo = file.type === "video/mp4" || file.type === "video/webm" || file.type === "video/quicktime";
|
|
8838
8910
|
const effectiveMax = isZip ? Math.max(baseMax, maxZipBytes) : isVideo ? Math.max(baseMax, maxVideoBytes) : baseMax;
|
|
8839
|
-
|
|
8840
|
-
|
|
8841
|
-
|
|
8842
|
-
|
|
8911
|
+
console.info("[upload] size check", {
|
|
8912
|
+
reqId,
|
|
8913
|
+
fileSize: file.size,
|
|
8914
|
+
effectiveMax,
|
|
8915
|
+
isZip,
|
|
8916
|
+
isVideo,
|
|
8917
|
+
isImage: file.type.startsWith("image/")
|
|
8843
8918
|
});
|
|
8919
|
+
if (file.size > effectiveMax) {
|
|
8920
|
+
console.error("[upload] file too large", {
|
|
8921
|
+
reqId,
|
|
8922
|
+
fileSize: file.size,
|
|
8923
|
+
effectiveMax,
|
|
8924
|
+
fileName: file.name
|
|
8925
|
+
});
|
|
8926
|
+
return json({
|
|
8927
|
+
error: "File size exceeds limit"
|
|
8928
|
+
}, {
|
|
8929
|
+
status: 400
|
|
8930
|
+
});
|
|
8931
|
+
}
|
|
8844
8932
|
const parentRaw = formData.get("parentId");
|
|
8845
8933
|
let parentId = null;
|
|
8846
8934
|
if (parentRaw != null && String(parentRaw).trim() !== "") {
|
|
8847
8935
|
const n = Number(parentRaw);
|
|
8848
|
-
if (!Number.isFinite(n))
|
|
8849
|
-
error
|
|
8850
|
-
|
|
8851
|
-
|
|
8852
|
-
|
|
8936
|
+
if (!Number.isFinite(n)) {
|
|
8937
|
+
console.error("[upload] invalid parentId", {
|
|
8938
|
+
reqId,
|
|
8939
|
+
parentRaw
|
|
8940
|
+
});
|
|
8941
|
+
return json({
|
|
8942
|
+
error: "Invalid parentId"
|
|
8943
|
+
}, {
|
|
8944
|
+
status: 400
|
|
8945
|
+
});
|
|
8946
|
+
}
|
|
8853
8947
|
parentId = n;
|
|
8854
8948
|
}
|
|
8855
8949
|
let folder = "";
|
|
8856
8950
|
if (parentId != null) {
|
|
8857
8951
|
if (!dataSource || !entityMap?.media) {
|
|
8952
|
+
console.error("[upload] missing dataSource/entityMap for folder upload", {
|
|
8953
|
+
reqId,
|
|
8954
|
+
parentId
|
|
8955
|
+
});
|
|
8858
8956
|
return json({
|
|
8859
8957
|
error: "Upload handler needs dataSource and entityMap for folder uploads"
|
|
8860
8958
|
}, {
|
|
@@ -8868,6 +8966,12 @@ function createUploadHandler(config) {
|
|
|
8868
8966
|
}
|
|
8869
8967
|
});
|
|
8870
8968
|
if (!p || p.kind !== "folder") {
|
|
8969
|
+
console.error("[upload] parent is not a folder", {
|
|
8970
|
+
reqId,
|
|
8971
|
+
parentId,
|
|
8972
|
+
found: Boolean(p),
|
|
8973
|
+
kind: p ? p.kind : null
|
|
8974
|
+
});
|
|
8871
8975
|
return json({
|
|
8872
8976
|
error: "parent must be a folder"
|
|
8873
8977
|
}, {
|
|
@@ -8875,25 +8979,90 @@ function createUploadHandler(config) {
|
|
|
8875
8979
|
});
|
|
8876
8980
|
}
|
|
8877
8981
|
folder = await relativePathFromMediaParentId(dataSource, entityMap, parentId);
|
|
8982
|
+
console.info("[upload] resolved folder from parentId", {
|
|
8983
|
+
reqId,
|
|
8984
|
+
parentId,
|
|
8985
|
+
folder
|
|
8986
|
+
});
|
|
8878
8987
|
} else {
|
|
8879
8988
|
const folderRawLegacy = formData.get("folder") ?? formData.get("folderPath");
|
|
8880
8989
|
if (folderRawLegacy && typeof folderRawLegacy === "string" && folderRawLegacy.trim()) {
|
|
8881
8990
|
folder = sanitizeMediaFolderPath(folderRawLegacy);
|
|
8991
|
+
console.info("[upload] resolved folder from legacy field", {
|
|
8992
|
+
reqId,
|
|
8993
|
+
folder
|
|
8994
|
+
});
|
|
8882
8995
|
}
|
|
8883
8996
|
}
|
|
8997
|
+
console.info("[upload] reading file into buffer", {
|
|
8998
|
+
reqId,
|
|
8999
|
+
fileName: file.name,
|
|
9000
|
+
fileType: file.type,
|
|
9001
|
+
fileSize: file.size
|
|
9002
|
+
});
|
|
8884
9003
|
const buffer = Buffer.from(await file.arrayBuffer());
|
|
8885
9004
|
const fileName = `${Date.now()}-${file.name}`;
|
|
8886
9005
|
const contentType = file.type || "application/octet-stream";
|
|
8887
9006
|
const relativeUnderUploads = folder ? `${folder}/${fileName}` : fileName;
|
|
9007
|
+
const storageKey = `uploads/${relativeUnderUploads}`;
|
|
9008
|
+
console.info("[upload] S3/storage key prepared", {
|
|
9009
|
+
reqId,
|
|
9010
|
+
originalFileName: file.name,
|
|
9011
|
+
stampedFileName: fileName,
|
|
9012
|
+
folder: folder || "(root)",
|
|
9013
|
+
relativeUnderUploads,
|
|
9014
|
+
storageKey,
|
|
9015
|
+
contentType,
|
|
9016
|
+
bytes: buffer.length
|
|
9017
|
+
});
|
|
8888
9018
|
const raw = typeof storage === "function" ? storage() : storage;
|
|
9019
|
+
console.info("[upload] resolving storage service", {
|
|
9020
|
+
reqId,
|
|
9021
|
+
storageKey,
|
|
9022
|
+
storageIsFunction: typeof storage === "function",
|
|
9023
|
+
rawIsPromise: raw instanceof Promise,
|
|
9024
|
+
rawIsNullish: raw == null
|
|
9025
|
+
});
|
|
8889
9026
|
const storageService = raw instanceof Promise ? await raw : raw;
|
|
9027
|
+
console.info("[upload] storage service resolved", {
|
|
9028
|
+
reqId,
|
|
9029
|
+
storageKey,
|
|
9030
|
+
hasStorageService: Boolean(storageService)
|
|
9031
|
+
});
|
|
8890
9032
|
if (storageService) {
|
|
8891
|
-
|
|
9033
|
+
console.info("[upload] calling storage.upload", {
|
|
9034
|
+
reqId,
|
|
9035
|
+
storageKey,
|
|
9036
|
+
contentType,
|
|
9037
|
+
bytes: buffer.length
|
|
9038
|
+
});
|
|
9039
|
+
const uploadStarted = Date.now();
|
|
9040
|
+
let fileUrl;
|
|
9041
|
+
try {
|
|
9042
|
+
fileUrl = await storageService.upload(buffer, storageKey, contentType);
|
|
9043
|
+
} catch (storageErr) {
|
|
9044
|
+
console.error("[upload] storage.upload threw", {
|
|
9045
|
+
reqId,
|
|
9046
|
+
storageKey,
|
|
9047
|
+
contentType,
|
|
9048
|
+
bytes: buffer.length,
|
|
9049
|
+
ms: Date.now() - uploadStarted,
|
|
9050
|
+
error: storageErr instanceof Error ? storageErr.message : String(storageErr),
|
|
9051
|
+
name: storageErr instanceof Error ? storageErr.name : void 0,
|
|
9052
|
+
stack: storageErr instanceof Error ? storageErr.stack : void 0,
|
|
9053
|
+
code: storageErr && typeof storageErr === "object" && ("Code" in storageErr || "code" in storageErr) ? storageErr.Code ?? storageErr.code : void 0,
|
|
9054
|
+
metadata: storageErr && typeof storageErr === "object" && "$metadata" in storageErr ? storageErr.$metadata : void 0
|
|
9055
|
+
});
|
|
9056
|
+
throw storageErr;
|
|
9057
|
+
}
|
|
8892
9058
|
console.info("[upload] stored via storage plugin", {
|
|
8893
|
-
|
|
9059
|
+
reqId,
|
|
9060
|
+
key: storageKey,
|
|
9061
|
+
fullS3KeyHint: storageKey,
|
|
8894
9062
|
contentType,
|
|
8895
9063
|
bytes: buffer.length,
|
|
8896
|
-
fileUrl
|
|
9064
|
+
fileUrl,
|
|
9065
|
+
ms: Date.now() - uploadStarted
|
|
8897
9066
|
});
|
|
8898
9067
|
return json({
|
|
8899
9068
|
filePath: fileUrl,
|
|
@@ -8901,8 +9070,10 @@ function createUploadHandler(config) {
|
|
|
8901
9070
|
});
|
|
8902
9071
|
}
|
|
8903
9072
|
console.warn("[upload] no storage plugin \u2014 writing local disk (broken on most deploys)", {
|
|
9073
|
+
reqId,
|
|
8904
9074
|
localUploadDir,
|
|
8905
|
-
key: relativeUnderUploads
|
|
9075
|
+
key: relativeUnderUploads,
|
|
9076
|
+
storageKey
|
|
8906
9077
|
});
|
|
8907
9078
|
const fs2 = await import('fs/promises');
|
|
8908
9079
|
const path2 = await import('path');
|
|
@@ -8913,6 +9084,12 @@ function createUploadHandler(config) {
|
|
|
8913
9084
|
});
|
|
8914
9085
|
await fs2.writeFile(filePath, buffer);
|
|
8915
9086
|
const urlRel = `${localUploadDir.replace(/^\/+/, "").replace(/\\/g, "/")}/${relativeUnderUploads.replace(/\\/g, "/")}`;
|
|
9087
|
+
console.info("[upload] local write ok", {
|
|
9088
|
+
reqId,
|
|
9089
|
+
diskPath: filePath,
|
|
9090
|
+
filePath: `/${urlRel}`,
|
|
9091
|
+
key: relativeUnderUploads
|
|
9092
|
+
});
|
|
8916
9093
|
return json({
|
|
8917
9094
|
filePath: `/${urlRel}`,
|
|
8918
9095
|
parentId
|
|
@@ -8921,11 +9098,13 @@ function createUploadHandler(config) {
|
|
|
8921
9098
|
const message = err instanceof Error ? err.message : String(err);
|
|
8922
9099
|
const awsMeta = err && typeof err === "object" && "$metadata" in err ? err.$metadata : void 0;
|
|
8923
9100
|
console.error("[upload] File upload failed", {
|
|
9101
|
+
reqId,
|
|
8924
9102
|
error: message,
|
|
8925
9103
|
stack: err instanceof Error ? err.stack : void 0,
|
|
8926
9104
|
name: err instanceof Error ? err.name : void 0,
|
|
8927
9105
|
code: err && typeof err === "object" && ("Code" in err || "code" in err) ? err.Code ?? err.code : void 0,
|
|
8928
|
-
metadata: awsMeta
|
|
9106
|
+
metadata: awsMeta,
|
|
9107
|
+
raw: err instanceof Error ? void 0 : String(err)
|
|
8929
9108
|
});
|
|
8930
9109
|
if (/Failed to parse body as FormData/i.test(message)) {
|
|
8931
9110
|
return json({
|
|
@@ -9262,13 +9441,43 @@ function createFormSaveHandlers(config) {
|
|
|
9262
9441
|
}
|
|
9263
9442
|
}
|
|
9264
9443
|
if (Object.keys(formRow).length > 0) await formRepo().update(formId, formRow);
|
|
9265
|
-
|
|
9266
|
-
formId
|
|
9267
|
-
});
|
|
9444
|
+
const incomingFieldIds = /* @__PURE__ */ new Set();
|
|
9268
9445
|
for (let i = 0; i < fields.length; i++) {
|
|
9269
|
-
const
|
|
9446
|
+
const f = fields[i];
|
|
9447
|
+
const fieldId = f.id != null && Number.isFinite(Number(f.id)) && Number(f.id) > 0 ? Number(f.id) : null;
|
|
9448
|
+
const row = normalizeFieldRow(f, formId);
|
|
9270
9449
|
row.order = i + 1;
|
|
9271
|
-
|
|
9450
|
+
if (fieldId) {
|
|
9451
|
+
const existingField = await fieldRepo().findOne({
|
|
9452
|
+
where: {
|
|
9453
|
+
id: fieldId,
|
|
9454
|
+
formId
|
|
9455
|
+
}
|
|
9456
|
+
});
|
|
9457
|
+
if (existingField) {
|
|
9458
|
+
incomingFieldIds.add(fieldId);
|
|
9459
|
+
await fieldRepo().update({
|
|
9460
|
+
id: fieldId,
|
|
9461
|
+
formId
|
|
9462
|
+
}, row);
|
|
9463
|
+
continue;
|
|
9464
|
+
}
|
|
9465
|
+
}
|
|
9466
|
+
const created = await fieldRepo().save(fieldRepo().create(row));
|
|
9467
|
+
if (created?.id) incomingFieldIds.add(created.id);
|
|
9468
|
+
}
|
|
9469
|
+
const allCurrentFields = await fieldRepo().find({
|
|
9470
|
+
where: {
|
|
9471
|
+
formId
|
|
9472
|
+
}
|
|
9473
|
+
});
|
|
9474
|
+
for (const existingField of allCurrentFields) {
|
|
9475
|
+
if (!incomingFieldIds.has(existingField.id)) {
|
|
9476
|
+
await fieldRepo().delete({
|
|
9477
|
+
id: existingField.id,
|
|
9478
|
+
formId
|
|
9479
|
+
});
|
|
9480
|
+
}
|
|
9272
9481
|
}
|
|
9273
9482
|
const saved = await formRepo().findOne({
|
|
9274
9483
|
where: {
|
|
@@ -9422,7 +9631,7 @@ function createFormSubmissionListHandler(config) {
|
|
|
9422
9631
|
const limit = Math.min(100, Number(searchParams.get("limit")) || 10);
|
|
9423
9632
|
const skip = (page - 1) * limit;
|
|
9424
9633
|
const sortField = searchParams.get("sortField") || "createdAt";
|
|
9425
|
-
const sortOrder = searchParams.get("sortOrder") === "
|
|
9634
|
+
const sortOrder = searchParams.get("sortOrder") === "asc" ? "ASC" : "DESC";
|
|
9426
9635
|
const [data, total] = await repo.findAndCount({
|
|
9427
9636
|
skip,
|
|
9428
9637
|
take: limit,
|
|
@@ -31194,7 +31403,7 @@ function createStorefrontApiHandler(config) {
|
|
|
31194
31403
|
const meta = it.metadata && typeof it.metadata === "object" && !Array.isArray(it.metadata) ? it.metadata : {};
|
|
31195
31404
|
const fromMeta = Number(meta.comboId ?? meta.combo_id);
|
|
31196
31405
|
if (Number.isInteger(fromMeta) && fromMeta > 0) return fromMeta;
|
|
31197
|
-
if (meta.isCombo === true || meta.type === "combo" || meta.lineType === "combo") {
|
|
31406
|
+
if (meta.isCombo === true || meta.type === "combo" || meta.lineType === "combo" || meta.lineKind === "combo" || meta.itemType === "combo") {
|
|
31198
31407
|
const pid = Number(it.productId);
|
|
31199
31408
|
if (Number.isInteger(pid) && pid > 0) return pid;
|
|
31200
31409
|
}
|
|
@@ -33323,7 +33532,10 @@ function createStorefrontApiHandler(config) {
|
|
|
33323
33532
|
});
|
|
33324
33533
|
if (existing) {
|
|
33325
33534
|
await cartItemRepo().update(existing.id, {
|
|
33326
|
-
quantity:
|
|
33535
|
+
quantity: gi.quantity,
|
|
33536
|
+
...gi.metadata ? {
|
|
33537
|
+
metadata: gi.metadata
|
|
33538
|
+
} : {}
|
|
33327
33539
|
});
|
|
33328
33540
|
} else {
|
|
33329
33541
|
await cartItemRepo().save(cartItemRepo().create({
|