@payloadcms/db-mongodb 3.9.0 → 3.10.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/count.d.ts.map +1 -1
- package/dist/count.js +20 -22
- package/dist/count.js.map +1 -1
- package/dist/countGlobalVersions.d.ts.map +1 -1
- package/dist/countGlobalVersions.js +20 -22
- package/dist/countGlobalVersions.js.map +1 -1
- package/dist/countVersions.d.ts.map +1 -1
- package/dist/countVersions.js +20 -22
- package/dist/countVersions.js.map +1 -1
- package/dist/create.d.ts.map +1 -1
- package/dist/create.js +23 -24
- package/dist/create.js.map +1 -1
- package/dist/createGlobal.d.ts.map +1 -1
- package/dist/createGlobal.js +22 -20
- package/dist/createGlobal.js.map +1 -1
- package/dist/createGlobalVersion.d.ts.map +1 -1
- package/dist/createGlobalVersion.js +36 -31
- package/dist/createGlobalVersion.js.map +1 -1
- package/dist/createVersion.d.ts.map +1 -1
- package/dist/createVersion.js +37 -32
- package/dist/createVersion.js.map +1 -1
- package/dist/deleteMany.d.ts.map +1 -1
- package/dist/deleteMany.js +7 -7
- package/dist/deleteMany.js.map +1 -1
- package/dist/deleteOne.d.ts.map +1 -1
- package/dist/deleteOne.js +18 -14
- package/dist/deleteOne.js.map +1 -1
- package/dist/deleteVersions.d.ts.map +1 -1
- package/dist/deleteVersions.js +7 -7
- package/dist/deleteVersions.js.map +1 -1
- package/dist/find.d.ts.map +1 -1
- package/dist/find.js +41 -74
- package/dist/find.js.map +1 -1
- package/dist/findGlobal.d.ts.map +1 -1
- package/dist/findGlobal.js +20 -19
- package/dist/findGlobal.js.map +1 -1
- package/dist/findGlobalVersions.d.ts.map +1 -1
- package/dist/findGlobalVersions.js +34 -63
- package/dist/findGlobalVersions.js.map +1 -1
- package/dist/findOne.d.ts.map +1 -1
- package/dist/findOne.js +33 -21
- package/dist/findOne.js.map +1 -1
- package/dist/findVersions.d.ts.map +1 -1
- package/dist/findVersions.js +34 -62
- package/dist/findVersions.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/migrateFresh.d.ts.map +1 -1
- package/dist/migrateFresh.js.map +1 -1
- package/dist/predefinedMigrations/migrateRelationshipsV2_V3.d.ts.map +1 -1
- package/dist/predefinedMigrations/migrateRelationshipsV2_V3.js +20 -16
- package/dist/predefinedMigrations/migrateRelationshipsV2_V3.js.map +1 -1
- package/dist/predefinedMigrations/migrateVersionsV1_V2.js +4 -4
- package/dist/predefinedMigrations/migrateVersionsV1_V2.js.map +1 -1
- package/dist/queries/buildAndOrConditions.d.ts +3 -1
- package/dist/queries/buildAndOrConditions.d.ts.map +1 -1
- package/dist/queries/buildAndOrConditions.js +2 -1
- package/dist/queries/buildAndOrConditions.js.map +1 -1
- package/dist/queries/buildQuery.d.ts +2 -0
- package/dist/queries/buildQuery.d.ts.map +1 -1
- package/dist/queries/buildQuery.js +2 -6
- package/dist/queries/buildQuery.js.map +1 -1
- package/dist/queries/buildSearchParams.d.ts +3 -1
- package/dist/queries/buildSearchParams.d.ts.map +1 -1
- package/dist/queries/buildSearchParams.js +15 -10
- package/dist/queries/buildSearchParams.js.map +1 -1
- package/dist/queries/buildSortParam.d.ts +1 -7
- package/dist/queries/buildSortParam.d.ts.map +1 -1
- package/dist/queries/buildSortParam.js +2 -2
- package/dist/queries/buildSortParam.js.map +1 -1
- package/dist/queries/getLocalizedSortProperty.js +2 -2
- package/dist/queries/getLocalizedSortProperty.js.map +1 -1
- package/dist/queries/parseParams.d.ts +3 -1
- package/dist/queries/parseParams.d.ts.map +1 -1
- package/dist/queries/parseParams.js +2 -1
- package/dist/queries/parseParams.js.map +1 -1
- package/dist/queries/sanitizeQueryValue.d.ts +2 -1
- package/dist/queries/sanitizeQueryValue.d.ts.map +1 -1
- package/dist/queries/sanitizeQueryValue.js +33 -6
- package/dist/queries/sanitizeQueryValue.js.map +1 -1
- package/dist/queryDrafts.d.ts.map +1 -1
- package/dist/queryDrafts.js +42 -66
- package/dist/queryDrafts.js.map +1 -1
- package/dist/updateGlobal.d.ts.map +1 -1
- package/dist/updateGlobal.js +27 -24
- package/dist/updateGlobal.js.map +1 -1
- package/dist/updateGlobalVersion.d.ts.map +1 -1
- package/dist/updateGlobalVersion.js +30 -28
- package/dist/updateGlobalVersion.js.map +1 -1
- package/dist/updateOne.d.ts.map +1 -1
- package/dist/updateOne.js +30 -25
- package/dist/updateOne.js.map +1 -1
- package/dist/updateVersion.d.ts.map +1 -1
- package/dist/updateVersion.js +30 -27
- package/dist/updateVersion.js.map +1 -1
- package/dist/upsert.d.ts.map +1 -1
- package/dist/upsert.js +1 -1
- package/dist/upsert.js.map +1 -1
- package/dist/utilities/buildJoinAggregation.d.ts +4 -4
- package/dist/utilities/buildJoinAggregation.d.ts.map +1 -1
- package/dist/utilities/buildJoinAggregation.js +13 -30
- package/dist/utilities/buildJoinAggregation.js.map +1 -1
- package/dist/utilities/buildProjectionFromSelect.d.ts.map +1 -1
- package/dist/utilities/buildProjectionFromSelect.js +18 -1
- package/dist/utilities/buildProjectionFromSelect.js.map +1 -1
- package/dist/utilities/findMany.d.ts +20 -0
- package/dist/utilities/findMany.d.ts.map +1 -0
- package/dist/utilities/findMany.js +84 -0
- package/dist/utilities/findMany.js.map +1 -0
- package/dist/utilities/getHasNearConstraint.d.ts +3 -0
- package/dist/utilities/getHasNearConstraint.d.ts.map +1 -0
- package/dist/utilities/getHasNearConstraint.js +26 -0
- package/dist/utilities/getHasNearConstraint.js.map +1 -0
- package/dist/utilities/getSession.d.ts +9 -0
- package/dist/utilities/getSession.d.ts.map +1 -0
- package/dist/{withSession.js → utilities/getSession.js} +7 -6
- package/dist/utilities/getSession.js.map +1 -0
- package/dist/utilities/handleError.d.ts +3 -2
- package/dist/utilities/handleError.d.ts.map +1 -1
- package/dist/utilities/handleError.js +8 -7
- package/dist/utilities/handleError.js.map +1 -1
- package/dist/utilities/transform.d.ts +25 -0
- package/dist/utilities/transform.d.ts.map +1 -0
- package/dist/utilities/transform.js +254 -0
- package/dist/utilities/transform.js.map +1 -0
- package/dist/utilities/{sanitizeRelationshipIDs.spec.js → transform.spec.js} +23 -7
- package/dist/utilities/transform.spec.js.map +1 -0
- package/package.json +4 -4
- package/dist/utilities/sanitizeInternalFields.d.ts +0 -2
- package/dist/utilities/sanitizeInternalFields.d.ts.map +0 -1
- package/dist/utilities/sanitizeInternalFields.js +0 -20
- package/dist/utilities/sanitizeInternalFields.js.map +0 -1
- package/dist/utilities/sanitizeRelationshipIDs.d.ts +0 -9
- package/dist/utilities/sanitizeRelationshipIDs.d.ts.map +0 -1
- package/dist/utilities/sanitizeRelationshipIDs.js +0 -125
- package/dist/utilities/sanitizeRelationshipIDs.js.map +0 -1
- package/dist/utilities/sanitizeRelationshipIDs.spec.js.map +0 -1
- package/dist/withSession.d.ts +0 -11
- package/dist/withSession.d.ts.map +0 -1
- package/dist/withSession.js.map +0 -1
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
export const findMany = async ({ adapter, collation, collection, joinAgreggation, limit, page = 1, pagination, projection, query = {}, session, skip, sort, useEstimatedCount })=>{
|
|
2
|
+
if (!skip) {
|
|
3
|
+
skip = (page - 1) * (limit ?? 0);
|
|
4
|
+
}
|
|
5
|
+
let docsPromise;
|
|
6
|
+
let countPromise = Promise.resolve(null);
|
|
7
|
+
if (joinAgreggation) {
|
|
8
|
+
const aggregation = collection.aggregate([
|
|
9
|
+
{
|
|
10
|
+
$match: query
|
|
11
|
+
}
|
|
12
|
+
], {
|
|
13
|
+
collation,
|
|
14
|
+
session
|
|
15
|
+
});
|
|
16
|
+
if (sort) {
|
|
17
|
+
aggregation.sort(sort);
|
|
18
|
+
}
|
|
19
|
+
if (skip) {
|
|
20
|
+
aggregation.skip(skip);
|
|
21
|
+
}
|
|
22
|
+
if (limit) {
|
|
23
|
+
aggregation.limit(limit);
|
|
24
|
+
}
|
|
25
|
+
for (const stage of joinAgreggation){
|
|
26
|
+
aggregation.addStage(stage);
|
|
27
|
+
}
|
|
28
|
+
if (projection) {
|
|
29
|
+
aggregation.project(projection);
|
|
30
|
+
}
|
|
31
|
+
docsPromise = aggregation.toArray();
|
|
32
|
+
} else {
|
|
33
|
+
docsPromise = collection.find(query, {
|
|
34
|
+
collation,
|
|
35
|
+
limit,
|
|
36
|
+
projection,
|
|
37
|
+
session,
|
|
38
|
+
skip,
|
|
39
|
+
sort
|
|
40
|
+
}).toArray();
|
|
41
|
+
}
|
|
42
|
+
if (pagination !== false && limit) {
|
|
43
|
+
if (useEstimatedCount) {
|
|
44
|
+
countPromise = collection.estimatedDocumentCount();
|
|
45
|
+
} else {
|
|
46
|
+
// Improve the performance of the countDocuments query which is used if useEstimatedCount is set to false by adding
|
|
47
|
+
// a hint. By default, if no hint is provided, MongoDB does not use an indexed field to count the returned documents,
|
|
48
|
+
// which makes queries very slow. This only happens when no query (filter) is provided. If one is provided, it uses
|
|
49
|
+
// the correct indexed field
|
|
50
|
+
const hint = adapter.disableIndexHints !== true ? {
|
|
51
|
+
_id: 1
|
|
52
|
+
} : undefined;
|
|
53
|
+
countPromise = collection.countDocuments(query, {
|
|
54
|
+
collation,
|
|
55
|
+
hint,
|
|
56
|
+
session
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const [docs, countResult] = await Promise.all([
|
|
61
|
+
docsPromise,
|
|
62
|
+
countPromise
|
|
63
|
+
]);
|
|
64
|
+
const count = countResult === null ? docs.length : countResult;
|
|
65
|
+
const totalPages = pagination !== false && typeof limit === 'number' && limit !== 0 ? Math.ceil(count / limit) : 1;
|
|
66
|
+
const hasPrevPage = pagination !== false && page > 1;
|
|
67
|
+
const hasNextPage = pagination !== false && totalPages > page;
|
|
68
|
+
const pagingCounter = pagination !== false && typeof limit === 'number' ? (page - 1) * limit + 1 : 1;
|
|
69
|
+
const result = {
|
|
70
|
+
docs,
|
|
71
|
+
hasNextPage,
|
|
72
|
+
hasPrevPage,
|
|
73
|
+
limit,
|
|
74
|
+
nextPage: hasNextPage ? page + 1 : null,
|
|
75
|
+
page,
|
|
76
|
+
pagingCounter,
|
|
77
|
+
prevPage: hasPrevPage ? page - 1 : null,
|
|
78
|
+
totalDocs: count,
|
|
79
|
+
totalPages
|
|
80
|
+
};
|
|
81
|
+
return result;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
//# sourceMappingURL=findMany.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/findMany.ts"],"sourcesContent":["import type { ClientSession, CollationOptions, Collection, Document } from 'mongodb'\nimport type { PipelineStage } from 'mongoose'\nimport type { PaginatedDocs } from 'payload'\n\nimport type { MongooseAdapter } from '../index.js'\n\nexport const findMany = async ({\n adapter,\n collation,\n collection,\n joinAgreggation,\n limit,\n page = 1,\n pagination,\n projection,\n query = {},\n session,\n skip,\n sort,\n useEstimatedCount,\n}: {\n adapter: MongooseAdapter\n collation?: CollationOptions\n collection: Collection\n joinAgreggation?: PipelineStage[]\n limit?: number\n page?: number\n pagination?: boolean\n projection?: Record<string, unknown>\n query?: Record<string, unknown>\n session?: ClientSession\n skip?: number\n sort?: Record<string, -1 | 1>\n useEstimatedCount?: boolean\n}): Promise<PaginatedDocs> => {\n if (!skip) {\n skip = (page - 1) * (limit ?? 0)\n }\n\n let docsPromise: Promise<Document[]>\n let countPromise: Promise<null | number> = Promise.resolve(null)\n\n if (joinAgreggation) {\n const aggregation = collection.aggregate(\n [\n {\n $match: query,\n },\n ],\n { collation, session },\n )\n\n if (sort) {\n aggregation.sort(sort)\n }\n\n if (skip) {\n aggregation.skip(skip)\n }\n\n if (limit) {\n aggregation.limit(limit)\n }\n\n for (const stage of joinAgreggation) {\n aggregation.addStage(stage)\n }\n\n if (projection) {\n aggregation.project(projection)\n }\n\n docsPromise = aggregation.toArray()\n } else {\n docsPromise = collection\n .find(query, {\n collation,\n limit,\n projection,\n session,\n skip,\n sort,\n })\n .toArray()\n }\n\n if (pagination !== false && limit) {\n if (useEstimatedCount) {\n countPromise = collection.estimatedDocumentCount()\n } else {\n // Improve the performance of the countDocuments query which is used if useEstimatedCount is set to false by adding\n // a hint. By default, if no hint is provided, MongoDB does not use an indexed field to count the returned documents,\n // which makes queries very slow. This only happens when no query (filter) is provided. If one is provided, it uses\n // the correct indexed field\n\n const hint = adapter.disableIndexHints !== true ? { _id: 1 } : undefined\n\n countPromise = collection.countDocuments(query, { collation, hint, session })\n }\n }\n\n const [docs, countResult] = await Promise.all([docsPromise, countPromise])\n\n const count = countResult === null ? docs.length : countResult\n\n const totalPages =\n pagination !== false && typeof limit === 'number' && limit !== 0 ? Math.ceil(count / limit) : 1\n\n const hasPrevPage = pagination !== false && page > 1\n const hasNextPage = pagination !== false && totalPages > page\n const pagingCounter =\n pagination !== false && typeof limit === 'number' ? (page - 1) * limit + 1 : 1\n\n const result = {\n docs,\n hasNextPage,\n hasPrevPage,\n limit,\n nextPage: hasNextPage ? page + 1 : null,\n page,\n pagingCounter,\n prevPage: hasPrevPage ? page - 1 : null,\n totalDocs: count,\n totalPages,\n } as PaginatedDocs<Record<string, unknown>>\n\n return result\n}\n"],"names":["findMany","adapter","collation","collection","joinAgreggation","limit","page","pagination","projection","query","session","skip","sort","useEstimatedCount","docsPromise","countPromise","Promise","resolve","aggregation","aggregate","$match","stage","addStage","project","toArray","find","estimatedDocumentCount","hint","disableIndexHints","_id","undefined","countDocuments","docs","countResult","all","count","length","totalPages","Math","ceil","hasPrevPage","hasNextPage","pagingCounter","result","nextPage","prevPage","totalDocs"],"mappings":"AAMA,OAAO,MAAMA,WAAW,OAAO,EAC7BC,OAAO,EACPC,SAAS,EACTC,UAAU,EACVC,eAAe,EACfC,KAAK,EACLC,OAAO,CAAC,EACRC,UAAU,EACVC,UAAU,EACVC,QAAQ,CAAC,CAAC,EACVC,OAAO,EACPC,IAAI,EACJC,IAAI,EACJC,iBAAiB,EAelB;IACC,IAAI,CAACF,MAAM;QACTA,OAAO,AAACL,CAAAA,OAAO,CAAA,IAAMD,CAAAA,SAAS,CAAA;IAChC;IAEA,IAAIS;IACJ,IAAIC,eAAuCC,QAAQC,OAAO,CAAC;IAE3D,IAAIb,iBAAiB;QACnB,MAAMc,cAAcf,WAAWgB,SAAS,CACtC;YACE;gBACEC,QAAQX;YACV;SACD,EACD;YAAEP;YAAWQ;QAAQ;QAGvB,IAAIE,MAAM;YACRM,YAAYN,IAAI,CAACA;QACnB;QAEA,IAAID,MAAM;YACRO,YAAYP,IAAI,CAACA;QACnB;QAEA,IAAIN,OAAO;YACTa,YAAYb,KAAK,CAACA;QACpB;QAEA,KAAK,MAAMgB,SAASjB,gBAAiB;YACnCc,YAAYI,QAAQ,CAACD;QACvB;QAEA,IAAIb,YAAY;YACdU,YAAYK,OAAO,CAACf;QACtB;QAEAM,cAAcI,YAAYM,OAAO;IACnC,OAAO;QACLV,cAAcX,WACXsB,IAAI,CAAChB,OAAO;YACXP;YACAG;YACAG;YACAE;YACAC;YACAC;QACF,GACCY,OAAO;IACZ;IAEA,IAAIjB,eAAe,SAASF,OAAO;QACjC,IAAIQ,mBAAmB;YACrBE,eAAeZ,WAAWuB,sBAAsB;QAClD,OAAO;YACL,mHAAmH;YACnH,qHAAqH;YACrH,mHAAmH;YACnH,4BAA4B;YAE5B,MAAMC,OAAO1B,QAAQ2B,iBAAiB,KAAK,OAAO;gBAAEC,KAAK;YAAE,IAAIC;YAE/Df,eAAeZ,WAAW4B,cAAc,CAACtB,OAAO;gBAAEP;gBAAWyB;gBAAMjB;YAAQ;QAC7E;IACF;IAEA,MAAM,CAACsB,MAAMC,YAAY,GAAG,MAAMjB,QAAQkB,GAAG,CAAC;QAACpB;QAAaC;KAAa;IAEzE,MAAMoB,QAAQF,gBAAgB,OAAOD,KAAKI,MAAM,GAAGH;IAEnD,MAAMI,aACJ9B,eAAe,SAAS,OAAOF,UAAU,YAAYA,UAAU,IAAIiC,KAAKC,IAAI,CAACJ,QAAQ9B,SAAS;IAEhG,MAAMmC,cAAcjC,eAAe,SAASD,OAAO;IACnD,MAAMmC,cAAclC,eAAe,SAAS8B,aAAa/B;IACzD,MAAMoC,gBACJnC,eAAe,SAAS,OAAOF,UAAU,WAAW,AAACC,CAAAA,OAAO,CAAA,IAAKD,QAAQ,IAAI;IAE/E,MAAMsC,SAAS;QACbX;QACAS;QACAD;QACAnC;QACAuC,UAAUH,cAAcnC,OAAO,IAAI;QACnCA;QACAoC;QACAG,UAAUL,cAAclC,OAAO,IAAI;QACnCwC,WAAWX;QACXE;IACF;IAEA,OAAOM;AACT,EAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getHasNearConstraint.d.ts","sourceRoot":"","sources":["../../src/utilities/getHasNearConstraint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAEpC,eAAO,MAAM,oBAAoB,WAAY,KAAK,KAAG,OAwBpD,CAAA"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export const getHasNearConstraint = (where)=>{
|
|
2
|
+
if (!where) {
|
|
3
|
+
return false;
|
|
4
|
+
}
|
|
5
|
+
for(const key in where){
|
|
6
|
+
const value = where[key];
|
|
7
|
+
if (Array.isArray(value) && [
|
|
8
|
+
'AND',
|
|
9
|
+
'OR'
|
|
10
|
+
].includes(key.toUpperCase())) {
|
|
11
|
+
for (const where of value){
|
|
12
|
+
if (getHasNearConstraint(where)) {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
for(const key in value){
|
|
18
|
+
if (key === 'near') {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return false;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
//# sourceMappingURL=getHasNearConstraint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/getHasNearConstraint.ts"],"sourcesContent":["import type { Where } from 'payload'\n\nexport const getHasNearConstraint = (where?: Where): boolean => {\n if (!where) {\n return false\n }\n\n for (const key in where) {\n const value = where[key]\n\n if (Array.isArray(value) && ['AND', 'OR'].includes(key.toUpperCase())) {\n for (const where of value) {\n if (getHasNearConstraint(where)) {\n return true\n }\n }\n }\n\n for (const key in value) {\n if (key === 'near') {\n return true\n }\n }\n }\n\n return false\n}\n"],"names":["getHasNearConstraint","where","key","value","Array","isArray","includes","toUpperCase"],"mappings":"AAEA,OAAO,MAAMA,uBAAuB,CAACC;IACnC,IAAI,CAACA,OAAO;QACV,OAAO;IACT;IAEA,IAAK,MAAMC,OAAOD,MAAO;QACvB,MAAME,QAAQF,KAAK,CAACC,IAAI;QAExB,IAAIE,MAAMC,OAAO,CAACF,UAAU;YAAC;YAAO;SAAK,CAACG,QAAQ,CAACJ,IAAIK,WAAW,KAAK;YACrE,KAAK,MAAMN,SAASE,MAAO;gBACzB,IAAIH,qBAAqBC,QAAQ;oBAC/B,OAAO;gBACT;YACF;QACF;QAEA,IAAK,MAAMC,OAAOC,MAAO;YACvB,IAAID,QAAQ,QAAQ;gBAClB,OAAO;YACT;QACF;IACF;IAEA,OAAO;AACT,EAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ClientSession } from 'mongoose';
|
|
2
|
+
import type { PayloadRequest } from 'payload';
|
|
3
|
+
import type { MongooseAdapter } from '../index.js';
|
|
4
|
+
/**
|
|
5
|
+
* returns the session belonging to the transaction of the req.session if exists
|
|
6
|
+
* @returns ClientSession
|
|
7
|
+
*/
|
|
8
|
+
export declare function getSession(db: MongooseAdapter, req?: Partial<PayloadRequest>): Promise<ClientSession | undefined>;
|
|
9
|
+
//# sourceMappingURL=getSession.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getSession.d.ts","sourceRoot":"","sources":["../../src/utilities/getSession.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAE7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAElD;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,EAAE,EAAE,eAAe,EACnB,GAAG,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAC5B,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAcpC"}
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* returns the session belonging to the transaction of the req.session if exists
|
|
3
3
|
* @returns ClientSession
|
|
4
|
-
*/ export async function
|
|
4
|
+
*/ export async function getSession(db, req) {
|
|
5
|
+
if (!req) {
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
5
8
|
let transactionID = req.transactionID;
|
|
6
9
|
if (transactionID instanceof Promise) {
|
|
7
10
|
transactionID = await req.transactionID;
|
|
8
11
|
}
|
|
9
|
-
if (
|
|
10
|
-
return db.sessions[transactionID]
|
|
11
|
-
session: db.sessions[transactionID]
|
|
12
|
-
} : {};
|
|
12
|
+
if (transactionID) {
|
|
13
|
+
return db.sessions[transactionID];
|
|
13
14
|
}
|
|
14
15
|
}
|
|
15
16
|
|
|
16
|
-
//# sourceMappingURL=
|
|
17
|
+
//# sourceMappingURL=getSession.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/getSession.ts"],"sourcesContent":["import type { ClientSession } from 'mongoose'\nimport type { PayloadRequest } from 'payload'\n\nimport type { MongooseAdapter } from '../index.js'\n\n/**\n * returns the session belonging to the transaction of the req.session if exists\n * @returns ClientSession\n */\nexport async function getSession(\n db: MongooseAdapter,\n req?: Partial<PayloadRequest>,\n): Promise<ClientSession | undefined> {\n if (!req) {\n return\n }\n\n let transactionID = req.transactionID\n\n if (transactionID instanceof Promise) {\n transactionID = await req.transactionID\n }\n\n if (transactionID) {\n return db.sessions[transactionID]\n }\n}\n"],"names":["getSession","db","req","transactionID","Promise","sessions"],"mappings":"AAKA;;;CAGC,GACD,OAAO,eAAeA,WACpBC,EAAmB,EACnBC,GAA6B;IAE7B,IAAI,CAACA,KAAK;QACR;IACF;IAEA,IAAIC,gBAAgBD,IAAIC,aAAa;IAErC,IAAIA,yBAAyBC,SAAS;QACpCD,gBAAgB,MAAMD,IAAIC,aAAa;IACzC;IAEA,IAAIA,eAAe;QACjB,OAAOF,GAAGI,QAAQ,CAACF,cAAc;IACnC;AACF"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import type { PayloadRequest } from 'payload';
|
|
1
2
|
export declare const handleError: ({ collection, error, global, req, }: {
|
|
2
3
|
collection?: string;
|
|
3
|
-
error:
|
|
4
|
+
error: unknown;
|
|
4
5
|
global?: string;
|
|
5
|
-
req
|
|
6
|
+
req?: Partial<PayloadRequest>;
|
|
6
7
|
}) => never;
|
|
7
8
|
//# sourceMappingURL=handleError.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handleError.d.ts","sourceRoot":"","sources":["../../src/utilities/handleError.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"handleError.d.ts","sourceRoot":"","sources":["../../src/utilities/handleError.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAK7C,eAAO,MAAM,WAAW,wCAKrB;IACD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,OAAO,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,GAAG,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAA;CAC9B,UAyBA,CAAA"}
|
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
import httpStatus from 'http-status';
|
|
2
2
|
import { APIError, ValidationError } from 'payload';
|
|
3
3
|
export const handleError = ({ collection, error, global, req })=>{
|
|
4
|
+
if (!error || typeof error !== 'object') {
|
|
5
|
+
throw error;
|
|
6
|
+
}
|
|
7
|
+
const message = req?.t ? req.t('error:valueMustBeUnique') : 'Value must be unique';
|
|
4
8
|
// Handle uniqueness error from MongoDB
|
|
5
|
-
if (error.code === 11000 && error.keyValue) {
|
|
9
|
+
if ('code' in error && error.code === 11000 && 'keyValue' in error && error.keyValue) {
|
|
6
10
|
throw new ValidationError({
|
|
7
11
|
collection,
|
|
8
12
|
errors: [
|
|
9
13
|
{
|
|
10
|
-
message
|
|
14
|
+
message,
|
|
11
15
|
path: Object.keys(error.keyValue)[0]
|
|
12
16
|
}
|
|
13
17
|
],
|
|
14
18
|
global
|
|
15
|
-
}, req
|
|
16
|
-
} else if (error.code === 11000) {
|
|
17
|
-
throw new APIError(req.t('error:valueMustBeUnique'), httpStatus.BAD_REQUEST);
|
|
18
|
-
} else {
|
|
19
|
-
throw error;
|
|
19
|
+
}, req?.t);
|
|
20
20
|
}
|
|
21
|
+
throw new APIError(message, httpStatus.BAD_REQUEST);
|
|
21
22
|
};
|
|
22
23
|
|
|
23
24
|
//# sourceMappingURL=handleError.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utilities/handleError.ts"],"sourcesContent":["import httpStatus from 'http-status'\nimport { APIError, ValidationError } from 'payload'\n\nexport const handleError = ({\n collection,\n error,\n global,\n req,\n}: {\n collection?: string\n error\n global?: string\n req
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/handleError.ts"],"sourcesContent":["import type { PayloadRequest } from 'payload'\n\nimport httpStatus from 'http-status'\nimport { APIError, ValidationError } from 'payload'\n\nexport const handleError = ({\n collection,\n error,\n global,\n req,\n}: {\n collection?: string\n error: unknown\n global?: string\n req?: Partial<PayloadRequest>\n}) => {\n if (!error || typeof error !== 'object') {\n throw error\n }\n\n const message = req?.t ? req.t('error:valueMustBeUnique') : 'Value must be unique'\n\n // Handle uniqueness error from MongoDB\n if ('code' in error && error.code === 11000 && 'keyValue' in error && error.keyValue) {\n throw new ValidationError(\n {\n collection,\n errors: [\n {\n message,\n path: Object.keys(error.keyValue)[0],\n },\n ],\n global,\n },\n req?.t,\n )\n }\n\n throw new APIError(message, httpStatus.BAD_REQUEST)\n}\n"],"names":["httpStatus","APIError","ValidationError","handleError","collection","error","global","req","message","t","code","keyValue","errors","path","Object","keys","BAD_REQUEST"],"mappings":"AAEA,OAAOA,gBAAgB,cAAa;AACpC,SAASC,QAAQ,EAAEC,eAAe,QAAQ,UAAS;AAEnD,OAAO,MAAMC,cAAc,CAAC,EAC1BC,UAAU,EACVC,KAAK,EACLC,MAAM,EACNC,GAAG,EAMJ;IACC,IAAI,CAACF,SAAS,OAAOA,UAAU,UAAU;QACvC,MAAMA;IACR;IAEA,MAAMG,UAAUD,KAAKE,IAAIF,IAAIE,CAAC,CAAC,6BAA6B;IAE5D,uCAAuC;IACvC,IAAI,UAAUJ,SAASA,MAAMK,IAAI,KAAK,SAAS,cAAcL,SAASA,MAAMM,QAAQ,EAAE;QACpF,MAAM,IAAIT,gBACR;YACEE;YACAQ,QAAQ;gBACN;oBACEJ;oBACAK,MAAMC,OAAOC,IAAI,CAACV,MAAMM,QAAQ,CAAC,CAAC,EAAE;gBACtC;aACD;YACDL;QACF,GACAC,KAAKE;IAET;IAEA,MAAM,IAAIR,SAASO,SAASR,WAAWgB,WAAW;AACpD,EAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { FlattenedField } from 'payload';
|
|
2
|
+
import type { MongooseAdapter } from '../index.js';
|
|
3
|
+
type Args = {
|
|
4
|
+
adapter: MongooseAdapter;
|
|
5
|
+
data: Record<string, unknown> | Record<string, unknown>[];
|
|
6
|
+
fields: FlattenedField[];
|
|
7
|
+
globalSlug?: string;
|
|
8
|
+
operation: 'create' | 'read' | 'update';
|
|
9
|
+
/**
|
|
10
|
+
* Set updatedAt and createdAt
|
|
11
|
+
* @default true
|
|
12
|
+
*/
|
|
13
|
+
timestamps?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Throw errors on invalid relationships
|
|
16
|
+
* @default true
|
|
17
|
+
*/
|
|
18
|
+
validateRelationships?: boolean;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* @experimental This API can be changed without a major version bump.
|
|
22
|
+
*/
|
|
23
|
+
export declare const transform: ({ adapter, data, fields, globalSlug, operation, timestamps, validateRelationships, }: Args) => void;
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=transform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../src/utilities/transform.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,cAAc,EAMf,MAAM,SAAS,CAAA;AAMhB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAElD,KAAK,IAAI,GAAG;IACV,OAAO,EAAE,eAAe,CAAA;IACxB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAA;IACzD,MAAM,EAAE,cAAc,EAAE,CAAA;IACxB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAA;IACvC;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;OAGG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAA;CAChC,CAAA;AAwMD;;GAEG;AACH,eAAO,MAAM,SAAS,yFAQnB,IAAI,SA4IN,CAAA"}
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import { Types } from 'mongoose';
|
|
2
|
+
import { traverseFields } from 'payload';
|
|
3
|
+
import { fieldAffectsData, fieldIsVirtual } from 'payload/shared';
|
|
4
|
+
function isValidRelationObject(value) {
|
|
5
|
+
return typeof value === 'object' && value !== null && 'relationTo' in value && 'value' in value;
|
|
6
|
+
}
|
|
7
|
+
const convertRelationshipValue = ({ operation, relatedCollection, validateRelationships, value })=>{
|
|
8
|
+
const customIDField = relatedCollection.fields.find((field)=>fieldAffectsData(field) && field.name === 'id');
|
|
9
|
+
if (operation === 'read') {
|
|
10
|
+
if (value instanceof Types.ObjectId) {
|
|
11
|
+
return value.toHexString();
|
|
12
|
+
}
|
|
13
|
+
return value;
|
|
14
|
+
}
|
|
15
|
+
if (customIDField) {
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
if (typeof value === 'string') {
|
|
19
|
+
try {
|
|
20
|
+
return new Types.ObjectId(value);
|
|
21
|
+
} catch (e) {
|
|
22
|
+
if (validateRelationships) {
|
|
23
|
+
throw e;
|
|
24
|
+
}
|
|
25
|
+
return value;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return value;
|
|
29
|
+
};
|
|
30
|
+
const sanitizeRelationship = ({ config, field, locale, operation, ref, validateRelationships, value })=>{
|
|
31
|
+
if (field.type === 'join') {
|
|
32
|
+
if (operation === 'read' && value && typeof value === 'object' && 'docs' in value && Array.isArray(value.docs)) {
|
|
33
|
+
for(let i = 0; i < value.docs.length; i++){
|
|
34
|
+
const item = value.docs[i];
|
|
35
|
+
if (item instanceof Types.ObjectId) {
|
|
36
|
+
value.docs[i] = item.toHexString();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
let relatedCollection;
|
|
43
|
+
let result = value;
|
|
44
|
+
const hasManyRelations = typeof field.relationTo !== 'string';
|
|
45
|
+
if (!hasManyRelations) {
|
|
46
|
+
relatedCollection = config.collections?.find(({ slug })=>slug === field.relationTo);
|
|
47
|
+
}
|
|
48
|
+
if (Array.isArray(value)) {
|
|
49
|
+
result = value.map((val)=>{
|
|
50
|
+
// Handle has many - polymorphic
|
|
51
|
+
if (isValidRelationObject(val)) {
|
|
52
|
+
const relatedCollectionForSingleValue = config.collections?.find(({ slug })=>slug === val.relationTo);
|
|
53
|
+
if (relatedCollectionForSingleValue) {
|
|
54
|
+
return {
|
|
55
|
+
relationTo: val.relationTo,
|
|
56
|
+
value: convertRelationshipValue({
|
|
57
|
+
operation,
|
|
58
|
+
relatedCollection: relatedCollectionForSingleValue,
|
|
59
|
+
validateRelationships,
|
|
60
|
+
value: val.value
|
|
61
|
+
})
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (relatedCollection) {
|
|
66
|
+
return convertRelationshipValue({
|
|
67
|
+
operation,
|
|
68
|
+
relatedCollection,
|
|
69
|
+
validateRelationships,
|
|
70
|
+
value: val
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
return val;
|
|
74
|
+
});
|
|
75
|
+
} else if (isValidRelationObject(value)) {
|
|
76
|
+
relatedCollection = config.collections?.find(({ slug })=>slug === value.relationTo);
|
|
77
|
+
if (relatedCollection) {
|
|
78
|
+
result = {
|
|
79
|
+
relationTo: value.relationTo,
|
|
80
|
+
value: convertRelationshipValue({
|
|
81
|
+
operation,
|
|
82
|
+
relatedCollection,
|
|
83
|
+
validateRelationships,
|
|
84
|
+
value: value.value
|
|
85
|
+
})
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
} else if (relatedCollection) {
|
|
89
|
+
result = convertRelationshipValue({
|
|
90
|
+
operation,
|
|
91
|
+
relatedCollection,
|
|
92
|
+
validateRelationships,
|
|
93
|
+
value
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
if (locale) {
|
|
97
|
+
ref[locale] = result;
|
|
98
|
+
} else {
|
|
99
|
+
ref[field.name] = result;
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* When sending data to Payload - convert Date to string.
|
|
104
|
+
* Vice versa when sending data to MongoDB so dates are stored properly.
|
|
105
|
+
*/ const sanitizeDate = ({ field, locale, operation, ref, value })=>{
|
|
106
|
+
if (!value) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (operation === 'read') {
|
|
110
|
+
if (value instanceof Date) {
|
|
111
|
+
value = value.toISOString();
|
|
112
|
+
}
|
|
113
|
+
} else {
|
|
114
|
+
if (typeof value === 'string') {
|
|
115
|
+
value = new Date(value);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (locale) {
|
|
119
|
+
ref[locale] = value;
|
|
120
|
+
} else {
|
|
121
|
+
ref[field.name] = value;
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* @experimental This API can be changed without a major version bump.
|
|
126
|
+
*/ export const transform = ({ adapter, data, fields, globalSlug, operation, timestamps = true, validateRelationships = true })=>{
|
|
127
|
+
if (Array.isArray(data)) {
|
|
128
|
+
for(let i = 0; i < data.length; i++){
|
|
129
|
+
transform({
|
|
130
|
+
adapter,
|
|
131
|
+
data: data[i],
|
|
132
|
+
fields,
|
|
133
|
+
globalSlug,
|
|
134
|
+
operation,
|
|
135
|
+
validateRelationships
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
const { payload: { config } } = adapter;
|
|
141
|
+
if (operation === 'read') {
|
|
142
|
+
delete data['__v'];
|
|
143
|
+
data.id = data._id;
|
|
144
|
+
delete data['_id'];
|
|
145
|
+
if (data.id instanceof Types.ObjectId) {
|
|
146
|
+
data.id = data.id.toHexString();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (operation !== 'read') {
|
|
150
|
+
if (timestamps) {
|
|
151
|
+
if (operation === 'create' && !data.createdAt) {
|
|
152
|
+
data.createdAt = new Date();
|
|
153
|
+
}
|
|
154
|
+
data.updatedAt = new Date();
|
|
155
|
+
}
|
|
156
|
+
if (globalSlug) {
|
|
157
|
+
data.globalType = globalSlug;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
const sanitize = ({ field, ref })=>{
|
|
161
|
+
if (!ref || typeof ref !== 'object') {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
if (operation !== 'read') {
|
|
165
|
+
if (typeof ref[field.name] === 'undefined' && typeof field.defaultValue !== 'undefined' && typeof field.defaultValue !== 'function') {
|
|
166
|
+
if (field.type === 'point') {
|
|
167
|
+
ref[field.name] = {
|
|
168
|
+
type: 'Point',
|
|
169
|
+
coordinates: field.defaultValue
|
|
170
|
+
};
|
|
171
|
+
} else {
|
|
172
|
+
ref[field.name] = field.defaultValue;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (fieldIsVirtual(field)) {
|
|
176
|
+
delete ref[field.name];
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (field.type === 'date') {
|
|
181
|
+
if (config.localization && field.localized) {
|
|
182
|
+
const fieldRef = ref[field.name];
|
|
183
|
+
if (!fieldRef || typeof fieldRef !== 'object') {
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
for (const locale of config.localization.localeCodes){
|
|
187
|
+
sanitizeDate({
|
|
188
|
+
field,
|
|
189
|
+
operation,
|
|
190
|
+
ref: fieldRef,
|
|
191
|
+
value: fieldRef[locale]
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
} else {
|
|
195
|
+
sanitizeDate({
|
|
196
|
+
field,
|
|
197
|
+
operation,
|
|
198
|
+
ref: ref,
|
|
199
|
+
value: ref[field.name]
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
if (field.type === 'relationship' || field.type === 'upload' || operation === 'read' && field.type === 'join') {
|
|
204
|
+
// sanitize passed undefined in objects to null
|
|
205
|
+
if (operation !== 'read' && field.name in ref && ref[field.name] === undefined) {
|
|
206
|
+
ref[field.name] = null;
|
|
207
|
+
}
|
|
208
|
+
if (!ref[field.name]) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
// handle localized relationships
|
|
212
|
+
if (config.localization && field.localized) {
|
|
213
|
+
const locales = config.localization.locales;
|
|
214
|
+
const fieldRef = ref[field.name];
|
|
215
|
+
if (typeof fieldRef !== 'object') {
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
for (const { code } of locales){
|
|
219
|
+
const value = ref[field.name][code];
|
|
220
|
+
if (value) {
|
|
221
|
+
sanitizeRelationship({
|
|
222
|
+
config,
|
|
223
|
+
field,
|
|
224
|
+
locale: code,
|
|
225
|
+
operation,
|
|
226
|
+
ref: fieldRef,
|
|
227
|
+
validateRelationships,
|
|
228
|
+
value
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
} else {
|
|
233
|
+
// handle non-localized relationships
|
|
234
|
+
sanitizeRelationship({
|
|
235
|
+
config,
|
|
236
|
+
field,
|
|
237
|
+
locale: undefined,
|
|
238
|
+
operation,
|
|
239
|
+
ref: ref,
|
|
240
|
+
validateRelationships,
|
|
241
|
+
value: ref[field.name]
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
traverseFields({
|
|
247
|
+
callback: sanitize,
|
|
248
|
+
fillEmpty: false,
|
|
249
|
+
flattenedFields: fields,
|
|
250
|
+
ref: data
|
|
251
|
+
});
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
//# sourceMappingURL=transform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/transform.ts"],"sourcesContent":["import type {\n CollectionConfig,\n DateField,\n FlattenedField,\n JoinField,\n RelationshipField,\n SanitizedConfig,\n TraverseFlattenedFieldsCallback,\n UploadField,\n} from 'payload'\n\nimport { Types } from 'mongoose'\nimport { traverseFields } from 'payload'\nimport { fieldAffectsData, fieldIsVirtual } from 'payload/shared'\n\nimport type { MongooseAdapter } from '../index.js'\n\ntype Args = {\n adapter: MongooseAdapter\n data: Record<string, unknown> | Record<string, unknown>[]\n fields: FlattenedField[]\n globalSlug?: string\n operation: 'create' | 'read' | 'update'\n /**\n * Set updatedAt and createdAt\n * @default true\n */\n timestamps?: boolean\n /**\n * Throw errors on invalid relationships\n * @default true\n */\n validateRelationships?: boolean\n}\n\ninterface RelationObject {\n relationTo: string\n value: number | string\n}\n\nfunction isValidRelationObject(value: unknown): value is RelationObject {\n return typeof value === 'object' && value !== null && 'relationTo' in value && 'value' in value\n}\n\nconst convertRelationshipValue = ({\n operation,\n relatedCollection,\n validateRelationships,\n value,\n}: {\n operation: Args['operation']\n relatedCollection: CollectionConfig\n validateRelationships?: boolean\n value: unknown\n}) => {\n const customIDField = relatedCollection.fields.find(\n (field) => fieldAffectsData(field) && field.name === 'id',\n )\n\n if (operation === 'read') {\n if (value instanceof Types.ObjectId) {\n return value.toHexString()\n }\n\n return value\n }\n\n if (customIDField) {\n return value\n }\n\n if (typeof value === 'string') {\n try {\n return new Types.ObjectId(value)\n } catch (e) {\n if (validateRelationships) {\n throw e\n }\n return value\n }\n }\n\n return value\n}\n\nconst sanitizeRelationship = ({\n config,\n field,\n locale,\n operation,\n ref,\n validateRelationships,\n value,\n}: {\n config: SanitizedConfig\n field: JoinField | RelationshipField | UploadField\n locale?: string\n operation: Args['operation']\n ref: Record<string, unknown>\n validateRelationships?: boolean\n value?: unknown\n}) => {\n if (field.type === 'join') {\n if (\n operation === 'read' &&\n value &&\n typeof value === 'object' &&\n 'docs' in value &&\n Array.isArray(value.docs)\n ) {\n for (let i = 0; i < value.docs.length; i++) {\n const item = value.docs[i]\n if (item instanceof Types.ObjectId) {\n value.docs[i] = item.toHexString()\n }\n }\n }\n\n return value\n }\n let relatedCollection: CollectionConfig | undefined\n let result = value\n\n const hasManyRelations = typeof field.relationTo !== 'string'\n\n if (!hasManyRelations) {\n relatedCollection = config.collections?.find(({ slug }) => slug === field.relationTo)\n }\n\n if (Array.isArray(value)) {\n result = value.map((val) => {\n // Handle has many - polymorphic\n if (isValidRelationObject(val)) {\n const relatedCollectionForSingleValue = config.collections?.find(\n ({ slug }) => slug === val.relationTo,\n )\n\n if (relatedCollectionForSingleValue) {\n return {\n relationTo: val.relationTo,\n value: convertRelationshipValue({\n operation,\n relatedCollection: relatedCollectionForSingleValue,\n validateRelationships,\n value: val.value,\n }),\n }\n }\n }\n\n if (relatedCollection) {\n return convertRelationshipValue({\n operation,\n relatedCollection,\n validateRelationships,\n value: val,\n })\n }\n\n return val\n })\n }\n // Handle has one - polymorphic\n else if (isValidRelationObject(value)) {\n relatedCollection = config.collections?.find(({ slug }) => slug === value.relationTo)\n\n if (relatedCollection) {\n result = {\n relationTo: value.relationTo,\n value: convertRelationshipValue({\n operation,\n relatedCollection,\n validateRelationships,\n value: value.value,\n }),\n }\n }\n }\n // Handle has one\n else if (relatedCollection) {\n result = convertRelationshipValue({\n operation,\n relatedCollection,\n validateRelationships,\n value,\n })\n }\n\n if (locale) {\n ref[locale] = result\n } else {\n ref[field.name] = result\n }\n}\n\n/**\n * When sending data to Payload - convert Date to string.\n * Vice versa when sending data to MongoDB so dates are stored properly.\n */\nconst sanitizeDate = ({\n field,\n locale,\n operation,\n ref,\n value,\n}: {\n field: DateField\n locale?: string\n operation: Args['operation']\n ref: Record<string, unknown>\n value: unknown\n}) => {\n if (!value) {\n return\n }\n\n if (operation === 'read') {\n if (value instanceof Date) {\n value = value.toISOString()\n }\n } else {\n if (typeof value === 'string') {\n value = new Date(value)\n }\n }\n\n if (locale) {\n ref[locale] = value\n } else {\n ref[field.name] = value\n }\n}\n\n/**\n * @experimental This API can be changed without a major version bump.\n */\nexport const transform = ({\n adapter,\n data,\n fields,\n globalSlug,\n operation,\n timestamps = true,\n validateRelationships = true,\n}: Args) => {\n if (Array.isArray(data)) {\n for (let i = 0; i < data.length; i++) {\n transform({ adapter, data: data[i], fields, globalSlug, operation, validateRelationships })\n }\n return\n }\n\n const {\n payload: { config },\n } = adapter\n\n if (operation === 'read') {\n delete data['__v']\n data.id = data._id\n delete data['_id']\n\n if (data.id instanceof Types.ObjectId) {\n data.id = data.id.toHexString()\n }\n }\n\n if (operation !== 'read') {\n if (timestamps) {\n if (operation === 'create' && !data.createdAt) {\n data.createdAt = new Date()\n }\n\n data.updatedAt = new Date()\n }\n\n if (globalSlug) {\n data.globalType = globalSlug\n }\n }\n\n const sanitize: TraverseFlattenedFieldsCallback = ({ field, ref }) => {\n if (!ref || typeof ref !== 'object') {\n return\n }\n\n if (operation !== 'read') {\n if (\n typeof ref[field.name] === 'undefined' &&\n typeof field.defaultValue !== 'undefined' &&\n typeof field.defaultValue !== 'function'\n ) {\n if (field.type === 'point') {\n ref[field.name] = {\n type: 'Point',\n coordinates: field.defaultValue,\n }\n } else {\n ref[field.name] = field.defaultValue\n }\n }\n\n if (fieldIsVirtual(field)) {\n delete ref[field.name]\n return\n }\n }\n\n if (field.type === 'date') {\n if (config.localization && field.localized) {\n const fieldRef = ref[field.name]\n if (!fieldRef || typeof fieldRef !== 'object') {\n return\n }\n\n for (const locale of config.localization.localeCodes) {\n sanitizeDate({\n field,\n operation,\n ref: fieldRef,\n value: fieldRef[locale],\n })\n }\n } else {\n sanitizeDate({\n field,\n operation,\n ref: ref as Record<string, unknown>,\n value: ref[field.name],\n })\n }\n }\n\n if (\n field.type === 'relationship' ||\n field.type === 'upload' ||\n (operation === 'read' && field.type === 'join')\n ) {\n // sanitize passed undefined in objects to null\n if (operation !== 'read' && field.name in ref && ref[field.name] === undefined) {\n ref[field.name] = null\n }\n\n if (!ref[field.name]) {\n return\n }\n\n // handle localized relationships\n if (config.localization && field.localized) {\n const locales = config.localization.locales\n const fieldRef = ref[field.name]\n if (typeof fieldRef !== 'object') {\n return\n }\n\n for (const { code } of locales) {\n const value = ref[field.name][code]\n if (value) {\n sanitizeRelationship({\n config,\n field,\n locale: code,\n operation,\n ref: fieldRef,\n validateRelationships,\n value,\n })\n }\n }\n } else {\n // handle non-localized relationships\n sanitizeRelationship({\n config,\n field,\n locale: undefined,\n operation,\n ref: ref as Record<string, unknown>,\n validateRelationships,\n value: ref[field.name],\n })\n }\n }\n }\n\n traverseFields({ callback: sanitize, fillEmpty: false, flattenedFields: fields, ref: data })\n}\n"],"names":["Types","traverseFields","fieldAffectsData","fieldIsVirtual","isValidRelationObject","value","convertRelationshipValue","operation","relatedCollection","validateRelationships","customIDField","fields","find","field","name","ObjectId","toHexString","e","sanitizeRelationship","config","locale","ref","type","Array","isArray","docs","i","length","item","result","hasManyRelations","relationTo","collections","slug","map","val","relatedCollectionForSingleValue","sanitizeDate","Date","toISOString","transform","adapter","data","globalSlug","timestamps","payload","id","_id","createdAt","updatedAt","globalType","sanitize","defaultValue","coordinates","localization","localized","fieldRef","localeCodes","undefined","locales","code","callback","fillEmpty","flattenedFields"],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { flattenAllFields } from 'payload';
|
|
1
2
|
import { Types } from 'mongoose';
|
|
2
|
-
import {
|
|
3
|
+
import { transform } from './transform.js';
|
|
3
4
|
const flattenRelationshipValues = (obj, prefix = '')=>{
|
|
4
5
|
return Object.keys(obj).reduce((acc, key)=>{
|
|
5
6
|
const fullKey = prefix ? `${prefix}.${key}` : key;
|
|
@@ -291,8 +292,8 @@ const relsData = {
|
|
|
291
292
|
]
|
|
292
293
|
}
|
|
293
294
|
};
|
|
294
|
-
describe('
|
|
295
|
-
it('should sanitize relationships', ()=>{
|
|
295
|
+
describe('transform', ()=>{
|
|
296
|
+
it('should sanitize relationships with transform write', ()=>{
|
|
296
297
|
const data = {
|
|
297
298
|
...relsData,
|
|
298
299
|
array: [
|
|
@@ -409,17 +410,32 @@ describe('sanitizeRelationshipIDs', ()=>{
|
|
|
409
410
|
}
|
|
410
411
|
};
|
|
411
412
|
const flattenValuesBefore = Object.values(flattenRelationshipValues(data));
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
413
|
+
const mockAdapter = {
|
|
414
|
+
payload: {
|
|
415
|
+
config
|
|
416
|
+
}
|
|
417
|
+
};
|
|
418
|
+
const fields = flattenAllFields({
|
|
415
419
|
fields: config.collections[0].fields
|
|
416
420
|
});
|
|
421
|
+
transform({
|
|
422
|
+
type: 'write',
|
|
423
|
+
adapter: mockAdapter,
|
|
424
|
+
data,
|
|
425
|
+
fields
|
|
426
|
+
});
|
|
417
427
|
const flattenValuesAfter = Object.values(flattenRelationshipValues(data));
|
|
418
428
|
flattenValuesAfter.forEach((value, i)=>{
|
|
419
429
|
expect(value).toBeInstanceOf(Types.ObjectId);
|
|
420
430
|
expect(flattenValuesBefore[i]).toBe(value.toHexString());
|
|
421
431
|
});
|
|
432
|
+
transform({
|
|
433
|
+
type: 'read',
|
|
434
|
+
adapter: mockAdapter,
|
|
435
|
+
data,
|
|
436
|
+
fields
|
|
437
|
+
});
|
|
422
438
|
});
|
|
423
439
|
});
|
|
424
440
|
|
|
425
|
-
//# sourceMappingURL=
|
|
441
|
+
//# sourceMappingURL=transform.spec.js.map
|