@payloadcms/figma 0.0.1-alpha.41 → 0.0.1-alpha.42
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/auth/oauth-flow.d.ts.map +1 -1
- package/dist/auth/oauth-flow.js +6 -3
- package/dist/auth/oauth-flow.js.map +1 -1
- package/dist/auth/refresh.d.ts +2 -1
- package/dist/auth/refresh.d.ts.map +1 -1
- package/dist/auth/refresh.js +11 -3
- package/dist/auth/refresh.js.map +1 -1
- package/dist/auth/token-store.d.ts +6 -4
- package/dist/auth/token-store.d.ts.map +1 -1
- package/dist/auth/token-store.js +17 -14
- package/dist/auth/token-store.js.map +1 -1
- package/dist/auth/types.d.ts +7 -4
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/auth/types.js.map +1 -1
- package/dist/cli.js +8 -6
- package/dist/cli.js.map +1 -1
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +2 -1
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +12 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/list-tokens.d.ts +3 -3
- package/dist/commands/list-tokens.d.ts.map +1 -1
- package/dist/commands/list-tokens.js +20 -8
- package/dist/commands/list-tokens.js.map +1 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +12 -4
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/logout.d.ts +5 -4
- package/dist/commands/logout.d.ts.map +1 -1
- package/dist/commands/logout.js +55 -12
- package/dist/commands/logout.js.map +1 -1
- package/dist/db-content-api/generated/content-api-types.d.ts +163 -103
- package/dist/db-content-api/generated/content-api-types.d.ts.map +1 -1
- package/dist/db-content-api/generated/content-api-types.js.map +1 -1
- package/dist/db-content-api/index.d.ts.map +1 -1
- package/dist/db-content-api/index.js +73 -65
- package/dist/db-content-api/index.js.map +1 -1
- package/dist/db-content-api/temp-utilities/unwrapDocument.d.ts +31 -1
- package/dist/db-content-api/temp-utilities/unwrapDocument.d.ts.map +1 -1
- package/dist/db-content-api/temp-utilities/unwrapDocument.js +24 -24
- package/dist/db-content-api/temp-utilities/unwrapDocument.js.map +1 -1
- package/dist/db-content-api/utilities/buildPathTypes.d.ts +12 -0
- package/dist/db-content-api/utilities/buildPathTypes.d.ts.map +1 -0
- package/dist/db-content-api/utilities/buildPathTypes.js +157 -0
- package/dist/db-content-api/utilities/buildPathTypes.js.map +1 -0
- package/dist/db-content-api/utilities/data/index.d.ts +2 -0
- package/dist/db-content-api/utilities/data/index.d.ts.map +1 -1
- package/dist/db-content-api/utilities/data/index.js +8 -0
- package/dist/db-content-api/utilities/data/index.js.map +1 -1
- package/dist/db-content-api/utilities/where.d.ts.map +1 -1
- package/dist/db-content-api/utilities/where.js +17 -3
- package/dist/db-content-api/utilities/where.js.map +1 -1
- package/dist/oauth/components/LogoutButton/index.d.ts.map +1 -1
- package/dist/oauth/components/LogoutButton/index.js +5 -3
- package/dist/oauth/components/LogoutButton/index.js.map +1 -1
- package/dist/oauth/endpoints/getLoginEndpoint.d.ts.map +1 -1
- package/dist/oauth/endpoints/getLoginEndpoint.js +17 -7
- package/dist/oauth/endpoints/getLoginEndpoint.js.map +1 -1
- package/dist/oauth/endpoints/getLogoutEndpoint.d.ts.map +1 -1
- package/dist/oauth/endpoints/getLogoutEndpoint.js +7 -4
- package/dist/oauth/endpoints/getLogoutEndpoint.js.map +1 -1
- package/dist/plugin/build-config.js +3 -3
- package/dist/plugin/build-config.js.map +1 -1
- package/dist/storage-content-api/api-types.d.ts +8 -1
- package/dist/storage-content-api/api-types.d.ts.map +1 -1
- package/dist/storage-content-api/api-types.js.map +1 -1
- package/dist/storage-content-api/client-uploads/generateSignedURL.js +1 -0
- package/dist/storage-content-api/client-uploads/generateSignedURL.js.map +1 -1
- package/dist/storage-content-api/generateURL.d.ts.map +1 -1
- package/dist/storage-content-api/generateURL.js +3 -2
- package/dist/storage-content-api/generateURL.js.map +1 -1
- package/dist/storage-content-api/handleDelete.d.ts.map +1 -1
- package/dist/storage-content-api/handleDelete.js +4 -2
- package/dist/storage-content-api/handleDelete.js.map +1 -1
- package/dist/storage-content-api/handleUpload.d.ts +1 -1
- package/dist/storage-content-api/handleUpload.d.ts.map +1 -1
- package/dist/storage-content-api/handleUpload.js +11 -3
- package/dist/storage-content-api/handleUpload.js.map +1 -1
- package/dist/storage-content-api/staticHandler.js +1 -0
- package/dist/storage-content-api/staticHandler.js.map +1 -1
- package/dist/utils/format-env-suffix.d.ts +12 -0
- package/dist/utils/format-env-suffix.d.ts.map +1 -0
- package/dist/utils/format-env-suffix.js +13 -0
- package/dist/utils/format-env-suffix.js.map +1 -0
- package/dist/utils/lambda-config.js +26 -12
- package/dist/utils/lambda-config.js.map +1 -1
- package/dist/utils/messages.d.ts.map +1 -1
- package/dist/utils/messages.js +1 -2
- package/dist/utils/messages.js.map +1 -1
- package/package.json +1 -1
- package/dist/db-content-api/temp-utilities/pagination.d.ts +0 -13
- package/dist/db-content-api/temp-utilities/pagination.d.ts.map +0 -1
- package/dist/db-content-api/temp-utilities/pagination.js +0 -45
- package/dist/db-content-api/temp-utilities/pagination.js.map +0 -1
- package/dist/oauth/utilities/getAdminPath.d.ts +0 -8
- package/dist/oauth/utilities/getAdminPath.d.ts.map +0 -1
- package/dist/oauth/utilities/getAdminPath.js +0 -9
- package/dist/oauth/utilities/getAdminPath.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/db-content-api/temp-utilities/unwrapDocument.ts"],"sourcesContent":["import type { Payload } from 'payload'\n\nimport type { components } from '../generated/content-api-types.js'\n\nimport { dataFromContentAPI } from '../utilities/data/index.js'\n\n// Helper to unwrap Content API document format to Payload format\n// Content API returns:\n// - For documents: { id,
|
|
1
|
+
{"version":3,"sources":["../../../src/db-content-api/temp-utilities/unwrapDocument.ts"],"sourcesContent":["import type { Payload } from 'payload'\n\nimport type { components } from '../generated/content-api-types.js'\n\nimport { dataFromContentAPI } from '../utilities/data/index.js'\n\ntype DocumentResponse = { id: string } & components['schemas']['Document']\ntype DocumentVersionResponse = { id: string } & components['schemas']['DocumentVersion']\n\n// Helper to unwrap Content API document format to Payload format\n// Content API returns:\n// - For documents: { id, contentSystemId, collection, doc: { ...fields, createdAt, updatedAt } }\n// - For versions: { id, contentSystemId, collection, versionDoc: { id, createdAt, updatedAt, latest, parent, version: {...fields} } }\n// Payload expects:\n// - For documents: { id, ...fields, createdAt, updatedAt }\n// - For versions: { id, parent, latest, version: { ...fields }, createdAt, updatedAt }\nexport function unwrapDocument(\n payload: Payload,\n doc: DocumentResponse | DocumentVersionResponse,\n collectionSlug?: string,\n): Record<string, unknown> {\n if (!doc) {\n return doc as unknown as Record<string, unknown>\n }\n\n // Check if this is a DocumentVersion (has versionDoc field)\n const isVersion = 'versionDoc' in doc\n\n if (isVersion) {\n // For versions, Payload expects nested structure with 'version' field\n const { versionDoc } = doc\n const baseDoc = { ...versionDoc } as Record<string, unknown>\n\n // Transform data from Content API format to Payload format\n if (collectionSlug) {\n // Only transform the nested 'version' field\n baseDoc.version = dataFromContentAPI(payload, collectionSlug, baseDoc.version) as Record<\n string,\n unknown\n >\n\n // Also convert version ID if collection uses numeric custom ID\n const customIDType = payload.collections?.[collectionSlug]?.customIDType\n if (customIDType === 'number') {\n baseDoc.id = Number(baseDoc.id)\n }\n }\n\n return baseDoc\n }\n\n // For regular documents, spread doc data at root level\n const { id, doc: docData } = doc\n const baseDoc = { ...docData, id }\n\n // Transform data from Content API format to Payload format\n if (collectionSlug) {\n return dataFromContentAPI(payload, collectionSlug, baseDoc) as Record<string, unknown>\n }\n\n return baseDoc\n}\n\nexport const unwrapFindResponse = (\n payload: Payload,\n response:\n | components['schemas']['FindDocumentsResponse']['result']\n | components['schemas']['FindDocumentVersionsResponse']['result'],\n collection: string,\n) => {\n const { data, ...paginationFields } = response\n return {\n docs: data.map((doc) =>\n unwrapDocument(payload, doc as DocumentResponse | DocumentVersionResponse, collection),\n ),\n ...paginationFields,\n }\n}\n"],"names":["dataFromContentAPI","unwrapDocument","payload","doc","collectionSlug","isVersion","versionDoc","baseDoc","version","customIDType","collections","id","Number","docData","unwrapFindResponse","response","collection","data","paginationFields","docs","map"],"mappings":"AAIA,SAASA,kBAAkB,QAAQ,6BAA4B;AAK/D,iEAAiE;AACjE,uBAAuB;AACvB,mGAAmG;AACnG,wIAAwI;AACxI,mBAAmB;AACnB,6DAA6D;AAC7D,yFAAyF;AACzF,OAAO,SAASC,eACdC,OAAgB,EAChBC,GAA+C,EAC/CC,cAAuB;IAEvB,IAAI,CAACD,KAAK;QACR,OAAOA;IACT;IAEA,4DAA4D;IAC5D,MAAME,YAAY,gBAAgBF;IAElC,IAAIE,WAAW;QACb,sEAAsE;QACtE,MAAM,EAAEC,UAAU,EAAE,GAAGH;QACvB,MAAMI,UAAU;YAAE,GAAGD,UAAU;QAAC;QAEhC,2DAA2D;QAC3D,IAAIF,gBAAgB;YAClB,4CAA4C;YAC5CG,QAAQC,OAAO,GAAGR,mBAAmBE,SAASE,gBAAgBG,QAAQC,OAAO;YAK7E,+DAA+D;YAC/D,MAAMC,eAAeP,QAAQQ,WAAW,EAAE,CAACN,eAAe,EAAEK;YAC5D,IAAIA,iBAAiB,UAAU;gBAC7BF,QAAQI,EAAE,GAAGC,OAAOL,QAAQI,EAAE;YAChC;QACF;QAEA,OAAOJ;IACT;IAEA,uDAAuD;IACvD,MAAM,EAAEI,EAAE,EAAER,KAAKU,OAAO,EAAE,GAAGV;IAC7B,MAAMI,UAAU;QAAE,GAAGM,OAAO;QAAEF;IAAG;IAEjC,2DAA2D;IAC3D,IAAIP,gBAAgB;QAClB,OAAOJ,mBAAmBE,SAASE,gBAAgBG;IACrD;IAEA,OAAOA;AACT;AAEA,OAAO,MAAMO,qBAAqB,CAChCZ,SACAa,UAGAC;IAEA,MAAM,EAAEC,IAAI,EAAE,GAAGC,kBAAkB,GAAGH;IACtC,OAAO;QACLI,MAAMF,KAAKG,GAAG,CAAC,CAACjB,MACdF,eAAeC,SAASC,KAAmDa;QAE7E,GAAGE,gBAAgB;IACrB;AACF,EAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Payload, Where } from 'payload';
|
|
2
|
+
/**
|
|
3
|
+
* Builds metadata for Content API request with pathTypes information
|
|
4
|
+
* Returns an object ready to spread into the request body
|
|
5
|
+
* This tells the Content API which paths are arrays/objects for proper query generation
|
|
6
|
+
*/
|
|
7
|
+
export declare function buildPathTypes(payload: Payload, collectionSlug: string, where: undefined | Where): {
|
|
8
|
+
meta?: {
|
|
9
|
+
pathTypes: Record<string, 'array'>;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=buildPathTypes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildPathTypes.d.ts","sourceRoot":"","sources":["../../../src/db-content-api/utilities/buildPathTypes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAS,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AA8JpD;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,OAAO,EAChB,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,SAAS,GAAG,KAAK,GACvB;IAAE,IAAI,CAAC,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAA;CAAE,CA2BnD"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extracts all field paths from a where clause recursively
|
|
3
|
+
*/ function extractPathsFromWhere(where, paths = new Set()) {
|
|
4
|
+
if (!where || typeof where !== 'object') {
|
|
5
|
+
return paths;
|
|
6
|
+
}
|
|
7
|
+
// Handle 'and' operator
|
|
8
|
+
if ('and' in where && Array.isArray(where.and)) {
|
|
9
|
+
for (const clause of where.and){
|
|
10
|
+
extractPathsFromWhere(clause, paths);
|
|
11
|
+
}
|
|
12
|
+
return paths;
|
|
13
|
+
}
|
|
14
|
+
// Handle 'or' operator
|
|
15
|
+
if ('or' in where && Array.isArray(where.or)) {
|
|
16
|
+
for (const clause of where.or){
|
|
17
|
+
extractPathsFromWhere(clause, paths);
|
|
18
|
+
}
|
|
19
|
+
return paths;
|
|
20
|
+
}
|
|
21
|
+
// Handle regular conditions - keys are field paths
|
|
22
|
+
for(const key in where){
|
|
23
|
+
if (key === 'and' || key === 'or') {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
// Add the path
|
|
27
|
+
paths.add(key);
|
|
28
|
+
// Check if the value is a nested where clause (for relationships)
|
|
29
|
+
const value = where[key];
|
|
30
|
+
if (value && typeof value === 'object' && !('equals' in value) && !('in' in value)) {
|
|
31
|
+
// Might be a nested where, recurse
|
|
32
|
+
extractPathsFromWhere(value, paths);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return paths;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Determines the type of a field based on its configuration
|
|
39
|
+
*/ function getFieldType(field) {
|
|
40
|
+
// Array field
|
|
41
|
+
if (field.type === 'array') {
|
|
42
|
+
return 'array';
|
|
43
|
+
}
|
|
44
|
+
// Blocks field (array of objects)
|
|
45
|
+
if (field.type === 'blocks') {
|
|
46
|
+
return 'array';
|
|
47
|
+
}
|
|
48
|
+
// Relationship field with hasMany (array)
|
|
49
|
+
if (field.type === 'relationship' && 'hasMany' in field && field.hasMany) {
|
|
50
|
+
return 'array';
|
|
51
|
+
}
|
|
52
|
+
// Select field with hasMany (array)
|
|
53
|
+
if (field.type === 'select' && 'hasMany' in field && field.hasMany) {
|
|
54
|
+
return 'array';
|
|
55
|
+
}
|
|
56
|
+
// Upload field with hasMany (array)
|
|
57
|
+
if (field.type === 'upload' && 'hasMany' in field && field.hasMany) {
|
|
58
|
+
return 'array';
|
|
59
|
+
}
|
|
60
|
+
// Objects (group, collapsible, row, tabs) don't need traversal
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Finds a field in the collection schema by its path
|
|
65
|
+
* Supports nested paths like "access.read.users"
|
|
66
|
+
*/ function findFieldByPath(payload, collectionSlug, path) {
|
|
67
|
+
const collectionConfig = payload.config.collections.find((c)=>c.slug === collectionSlug);
|
|
68
|
+
if (!collectionConfig) {
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
const pathSegments = path.split('.');
|
|
72
|
+
// Walk through the path segments to find the field
|
|
73
|
+
let currentFields = collectionConfig.fields;
|
|
74
|
+
let currentField = undefined;
|
|
75
|
+
for(let i = 0; i < pathSegments.length; i++){
|
|
76
|
+
const segment = pathSegments[i];
|
|
77
|
+
// First try to find a direct match
|
|
78
|
+
currentField = currentFields.find((f)=>'name' in f && f.name === segment);
|
|
79
|
+
// If not found, check if any unnamed container fields (collapsible, row) contain it
|
|
80
|
+
if (!currentField) {
|
|
81
|
+
for (const field of currentFields){
|
|
82
|
+
if (!('name' in field) || !field.name) {
|
|
83
|
+
// This is an unnamed field, check its contents
|
|
84
|
+
if ('fields' in field && field.type === 'collapsible' || 'fields' in field && field.type === 'row') {
|
|
85
|
+
currentField = field.fields.find((f)=>'name' in f && f.name === segment);
|
|
86
|
+
if (currentField) {
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
} else if ('tabs' in field && field.type === 'tabs') {
|
|
90
|
+
// Check all tabs
|
|
91
|
+
for (const tab of field.tabs){
|
|
92
|
+
currentField = tab.fields.find((f)=>'name' in f && f.name === segment);
|
|
93
|
+
if (currentField) {
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (currentField) {
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (!currentField) {
|
|
105
|
+
return undefined;
|
|
106
|
+
}
|
|
107
|
+
// If we're not at the end, get nested fields
|
|
108
|
+
if (i < pathSegments.length - 1) {
|
|
109
|
+
if (currentField.type === 'group' && 'fields' in currentField) {
|
|
110
|
+
currentFields = currentField.fields;
|
|
111
|
+
} else if (currentField.type === 'array' && 'fields' in currentField) {
|
|
112
|
+
currentFields = currentField.fields;
|
|
113
|
+
} else if (currentField.type === 'blocks' && 'blocks' in currentField) {
|
|
114
|
+
// For blocks, we can't determine the exact field without knowing the block type
|
|
115
|
+
// Return the blocks field itself
|
|
116
|
+
return currentField;
|
|
117
|
+
} else {
|
|
118
|
+
// Field doesn't have nested fields, can't continue
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return currentField;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Builds metadata for Content API request with pathTypes information
|
|
127
|
+
* Returns an object ready to spread into the request body
|
|
128
|
+
* This tells the Content API which paths are arrays/objects for proper query generation
|
|
129
|
+
*/ export function buildPathTypes(payload, collectionSlug, where) {
|
|
130
|
+
if (!where) {
|
|
131
|
+
return {};
|
|
132
|
+
}
|
|
133
|
+
const pathTypes = {};
|
|
134
|
+
const paths = extractPathsFromWhere(where);
|
|
135
|
+
for (const path of paths){
|
|
136
|
+
// For each path, we need to check all segments to see if any intermediate ones are arrays/objects
|
|
137
|
+
const segments = path.split('.');
|
|
138
|
+
for(let i = 0; i < segments.length; i++){
|
|
139
|
+
const partialPath = segments.slice(0, i + 1).join('.');
|
|
140
|
+
const field = findFieldByPath(payload, collectionSlug, partialPath);
|
|
141
|
+
if (field) {
|
|
142
|
+
const fieldType = getFieldType(field);
|
|
143
|
+
if (fieldType === 'array') {
|
|
144
|
+
pathTypes[partialPath] = fieldType;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// Only include meta if there are pathTypes
|
|
150
|
+
return Object.keys(pathTypes).length > 0 ? {
|
|
151
|
+
meta: {
|
|
152
|
+
pathTypes
|
|
153
|
+
}
|
|
154
|
+
} : {};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
//# sourceMappingURL=buildPathTypes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/db-content-api/utilities/buildPathTypes.ts"],"sourcesContent":["import type { Field, Payload, Where } from 'payload'\n\n/**\n * Extracts all field paths from a where clause recursively\n */\nfunction extractPathsFromWhere(where: Where, paths: Set<string> = new Set()): Set<string> {\n if (!where || typeof where !== 'object') {\n return paths\n }\n\n // Handle 'and' operator\n if ('and' in where && Array.isArray(where.and)) {\n for (const clause of where.and) {\n extractPathsFromWhere(clause, paths)\n }\n return paths\n }\n\n // Handle 'or' operator\n if ('or' in where && Array.isArray(where.or)) {\n for (const clause of where.or) {\n extractPathsFromWhere(clause, paths)\n }\n return paths\n }\n\n // Handle regular conditions - keys are field paths\n for (const key in where) {\n if (key === 'and' || key === 'or') {\n continue\n }\n\n // Add the path\n paths.add(key)\n\n // Check if the value is a nested where clause (for relationships)\n const value = where[key]\n if (value && typeof value === 'object' && !('equals' in value) && !('in' in value)) {\n // Might be a nested where, recurse\n extractPathsFromWhere(value as Where, paths)\n }\n }\n\n return paths\n}\n\n/**\n * Determines the type of a field based on its configuration\n */\nfunction getFieldType(field: Field): 'array' | null {\n // Array field\n if (field.type === 'array') {\n return 'array'\n }\n\n // Blocks field (array of objects)\n if (field.type === 'blocks') {\n return 'array'\n }\n\n // Relationship field with hasMany (array)\n if (field.type === 'relationship' && 'hasMany' in field && field.hasMany) {\n return 'array'\n }\n\n // Select field with hasMany (array)\n if (field.type === 'select' && 'hasMany' in field && field.hasMany) {\n return 'array'\n }\n\n // Upload field with hasMany (array)\n if (field.type === 'upload' && 'hasMany' in field && field.hasMany) {\n return 'array'\n }\n\n // Objects (group, collapsible, row, tabs) don't need traversal\n return null\n}\n\n/**\n * Finds a field in the collection schema by its path\n * Supports nested paths like \"access.read.users\"\n */\nfunction findFieldByPath(\n payload: Payload,\n collectionSlug: string,\n path: string,\n): Field | undefined {\n const collectionConfig = payload.config.collections.find((c) => c.slug === collectionSlug)\n if (!collectionConfig) {\n return undefined\n }\n\n const pathSegments = path.split('.')\n\n // Walk through the path segments to find the field\n let currentFields = collectionConfig.fields\n let currentField: Field | undefined = undefined\n\n for (let i = 0; i < pathSegments.length; i++) {\n const segment = pathSegments[i]\n\n // First try to find a direct match\n currentField = currentFields.find((f) => 'name' in f && f.name === segment)\n\n // If not found, check if any unnamed container fields (collapsible, row) contain it\n if (!currentField) {\n for (const field of currentFields) {\n if (!('name' in field) || !field.name) {\n // This is an unnamed field, check its contents\n if (\n ('fields' in field && field.type === 'collapsible') ||\n ('fields' in field && field.type === 'row')\n ) {\n currentField = field.fields.find((f) => 'name' in f && f.name === segment)\n if (currentField) {\n break\n }\n } else if ('tabs' in field && field.type === 'tabs') {\n // Check all tabs\n for (const tab of field.tabs) {\n currentField = tab.fields.find((f) => 'name' in f && f.name === segment)\n if (currentField) {\n break\n }\n }\n if (currentField) {\n break\n }\n }\n }\n }\n }\n\n if (!currentField) {\n return undefined\n }\n\n // If we're not at the end, get nested fields\n if (i < pathSegments.length - 1) {\n if (currentField.type === 'group' && 'fields' in currentField) {\n currentFields = currentField.fields\n } else if (currentField.type === 'array' && 'fields' in currentField) {\n currentFields = currentField.fields\n } else if (currentField.type === 'blocks' && 'blocks' in currentField) {\n // For blocks, we can't determine the exact field without knowing the block type\n // Return the blocks field itself\n return currentField\n } else {\n // Field doesn't have nested fields, can't continue\n return undefined\n }\n }\n }\n\n return currentField\n}\n\n/**\n * Builds metadata for Content API request with pathTypes information\n * Returns an object ready to spread into the request body\n * This tells the Content API which paths are arrays/objects for proper query generation\n */\nexport function buildPathTypes(\n payload: Payload,\n collectionSlug: string,\n where: undefined | Where,\n): { meta?: { pathTypes: Record<string, 'array'> } } {\n if (!where) {\n return {}\n }\n\n const pathTypes: Record<string, 'array'> = {}\n const paths = extractPathsFromWhere(where)\n\n for (const path of paths) {\n // For each path, we need to check all segments to see if any intermediate ones are arrays/objects\n const segments = path.split('.')\n\n for (let i = 0; i < segments.length; i++) {\n const partialPath = segments.slice(0, i + 1).join('.')\n const field = findFieldByPath(payload, collectionSlug, partialPath)\n\n if (field) {\n const fieldType = getFieldType(field)\n if (fieldType === 'array') {\n pathTypes[partialPath] = fieldType\n }\n }\n }\n }\n\n // Only include meta if there are pathTypes\n return Object.keys(pathTypes).length > 0 ? { meta: { pathTypes } } : {}\n}\n"],"names":["extractPathsFromWhere","where","paths","Set","Array","isArray","and","clause","or","key","add","value","getFieldType","field","type","hasMany","findFieldByPath","payload","collectionSlug","path","collectionConfig","config","collections","find","c","slug","undefined","pathSegments","split","currentFields","fields","currentField","i","length","segment","f","name","tab","tabs","buildPathTypes","pathTypes","segments","partialPath","slice","join","fieldType","Object","keys","meta"],"mappings":"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"}
|
|
@@ -9,11 +9,13 @@ type DataWithOperations = components['schemas']['DataWithOperations'];
|
|
|
9
9
|
* - Type casting: Convert values to match field types (e.g., number -> string for text fields)
|
|
10
10
|
* - RichText fields: Objects -> JSON strings
|
|
11
11
|
* - Virtual fields: Remove fields with `virtual: true` (pure virtual fields should never be saved)
|
|
12
|
+
* - Timestamps: Add updatedAt (always), and createdAt (when createdAt=true)
|
|
12
13
|
*
|
|
13
14
|
* Note: Date fields are automatically converted to ISO strings by JSON.stringify()
|
|
14
15
|
*/
|
|
15
16
|
export declare function dataToContentAPI(payload: Payload, collectionSlug: string, data: unknown, options?: {
|
|
16
17
|
applyDefaults?: boolean;
|
|
18
|
+
createdAt?: boolean;
|
|
17
19
|
}): DataWithOperations;
|
|
18
20
|
/**
|
|
19
21
|
* Transform data received from Content API (READ operations)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/db-content-api/utilities/data/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkC,OAAO,EAA0B,MAAM,SAAS,CAAA;AAI9F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sCAAsC,CAAA;AAOtE,KAAK,kBAAkB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,oBAAoB,CAAC,CAAA;AAErE
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/db-content-api/utilities/data/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkC,OAAO,EAA0B,MAAM,SAAS,CAAA;AAI9F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sCAAsC,CAAA;AAOtE,KAAK,kBAAkB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,oBAAoB,CAAC,CAAA;AAErE;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,OAAO,EAChB,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,OAAO,EACb,OAAO,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GACzD,kBAAkB,CA8EpB;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,OAAO,EAChB,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,OAAO,GACZ,OAAO,CA0FT"}
|
|
@@ -11,6 +11,7 @@ import { stripFields } from './stripFields.js';
|
|
|
11
11
|
* - Type casting: Convert values to match field types (e.g., number -> string for text fields)
|
|
12
12
|
* - RichText fields: Objects -> JSON strings
|
|
13
13
|
* - Virtual fields: Remove fields with `virtual: true` (pure virtual fields should never be saved)
|
|
14
|
+
* - Timestamps: Add updatedAt (always), and createdAt (when createdAt=true)
|
|
14
15
|
*
|
|
15
16
|
* Note: Date fields are automatically converted to ISO strings by JSON.stringify()
|
|
16
17
|
*/ export function dataToContentAPI(payload, collectionSlug, data, options) {
|
|
@@ -78,6 +79,13 @@ import { stripFields } from './stripFields.js';
|
|
|
78
79
|
if (customIDType === 'number') {
|
|
79
80
|
transformed.id = String(transformed.id);
|
|
80
81
|
}
|
|
82
|
+
// Add timestamps (Content API no longer auto-sets these in DB)
|
|
83
|
+
// updatedAt is always set, createdAt only on create operations
|
|
84
|
+
const now = new Date().toISOString();
|
|
85
|
+
transformed.updatedAt = now;
|
|
86
|
+
if (options?.createdAt) {
|
|
87
|
+
transformed.createdAt = now;
|
|
88
|
+
}
|
|
81
89
|
return transformed;
|
|
82
90
|
}
|
|
83
91
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/db-content-api/utilities/data/index.ts"],"sourcesContent":["import type { CollectionConfig, GlobalConfig, Payload, TraverseFieldsCallback } from 'payload'\n\nimport { flattenAllFields, traverseFields } from 'payload'\n\nimport type { components } from '../../generated/content-api-types.js'\n\nimport { applyDefaults } from './applyDefaults.js'\nimport { castFieldValue } from './castFieldValue.js'\nimport { removeVirtualFields } from './removeVirtualFields.js'\nimport { stripFields } from './stripFields.js'\n\ntype DataWithOperations = components['schemas']['DataWithOperations']\n\n/**\n * Transform data before sending to Content API (WRITE operations)\n *\n * Conversions applied:\n * - Default values: Apply static defaults for undefined fields (when applyDefaults=true)\n * - Type casting: Convert values to match field types (e.g., number -> string for text fields)\n * - RichText fields: Objects -> JSON strings\n * - Virtual fields: Remove fields with `virtual: true` (pure virtual fields should never be saved)\n *\n * Note: Date fields are automatically converted to ISO strings by JSON.stringify()\n */\nexport function dataToContentAPI(\n payload: Payload,\n collectionSlug: string,\n data: unknown,\n options?: { applyDefaults?: boolean },\n): DataWithOperations {\n if (!data || typeof data !== 'object') {\n return data as DataWithOperations\n }\n\n // Deep clone to avoid mutating original data\n const transformed = JSON.parse(JSON.stringify(data))\n\n // Get collection config\n const isGlobal = collectionSlug.startsWith('_global-')\n const actualSlug = isGlobal ? collectionSlug.substring(8) : collectionSlug\n const collectionConfig: CollectionConfig | GlobalConfig | undefined = isGlobal\n ? payload.config.globals?.find((g) => g.slug === actualSlug)\n : payload.config.collections.find((c) => c.slug === actualSlug)\n\n if (!collectionConfig?.fields) {\n return transformed as DataWithOperations\n }\n\n // Apply static defaults recursively to handle nested structures (arrays, groups)\n // This must happen before traverseFields to ensure defaults are in place\n if (options?.applyDefaults) {\n applyDefaults(transformed, collectionConfig.fields)\n }\n\n // Use Payload's traverseFields to iterate over all fields for transformations\n const callback: TraverseFieldsCallback = ({ field, ref }) => {\n if (!('name' in field) || !field.name) {\n return\n }\n if (!ref || typeof ref !== 'object') {\n return\n }\n\n const current = ref as Record<string, unknown>\n let value = current[field.name]\n\n // Transform existing values\n if (value !== null && value !== undefined) {\n // Step 1: Apply type casting (e.g., number -> string for text fields)\n value = castFieldValue(field, value)\n current[field.name] = value\n\n // Step 2: Apply Content API specific transformations\n // RichText: object -> JSON string\n if (field.type === 'richText' && typeof value !== 'string') {\n current[field.name] = JSON.stringify(value)\n }\n // Date fields are already handled by JSON.stringify() which converts Date -> ISO string\n }\n }\n\n traverseFields({ callback, fields: collectionConfig.fields, fillEmpty: false, ref: transformed })\n\n stripFields({\n config: payload.config,\n data: transformed,\n fields: flattenAllFields({ cache: true, fields: collectionConfig.fields }),\n reservedKeys: ['id', 'globalType'],\n })\n\n removeVirtualFields(transformed, collectionConfig.fields)\n\n // Convert numeric ID to string for Content API\n const customIDType = payload.collections?.[collectionSlug]?.customIDType\n if (customIDType === 'number') {\n transformed.id = String(transformed.id)\n }\n\n return transformed as DataWithOperations\n}\n\n/**\n * Transform data received from Content API (READ operations)\n *\n * Conversions applied:\n * - RichText fields: JSON strings -> Objects\n * - Virtual fields: Remove fields with `virtual: true` (should not be in DB but Content API backend may add them)\n *\n * Note: Date fields come as ISO strings from Content API and stay as strings\n * (matching MongoDB and other adapters' behavior)\n */\nexport function dataFromContentAPI(\n payload: Payload,\n collectionSlug: string,\n data: unknown,\n): unknown {\n if (!data || typeof data !== 'object') {\n return data\n }\n\n // Deep clone to avoid mutating original data\n const transformed = JSON.parse(JSON.stringify(data))\n\n // Get collection config\n const isGlobal = collectionSlug.startsWith('_global-')\n const actualSlug = isGlobal ? collectionSlug.substring(8) : collectionSlug\n const collectionConfig: CollectionConfig | GlobalConfig | undefined = isGlobal\n ? payload.config.globals?.find((g) => g.slug === actualSlug)\n : payload.config.collections.find((c) => c.slug === actualSlug)\n\n if (!collectionConfig?.fields) {\n return transformed\n }\n\n // Use Payload's traverseFields to iterate over all fields\n const callback: TraverseFieldsCallback = ({ field, parentPath, ref }) => {\n if (!('name' in field) || !field.name) {\n return\n }\n if (!ref || typeof ref !== 'object') {\n return\n }\n\n const current = ref as Record<string, unknown>\n const value = current[field.name]\n\n // Normalize undefined → null for optional fields\n // Content API may omit fields (undefined) but Payload expects null for optional fields\n if (value === undefined) {\n const isRequired = 'required' in field && field.required\n if (!isRequired) {\n current[field.name] = null\n }\n return\n }\n\n if (value !== null) {\n // RichText: JSON string -> object\n if (field.type === 'richText' && typeof value === 'string') {\n try {\n current[field.name] = JSON.parse(value)\n } catch (error) {\n const fieldPath = parentPath ? `${parentPath}.${field.name}` : field.name\n payload.logger.warn({\n err: error instanceof Error ? error : new Error(String(error)),\n msg: `Failed to parse richtext field '${fieldPath}' in collection '${collectionSlug}'`,\n })\n }\n }\n // Date fields: Already ISO strings from Content API, no conversion needed\n }\n }\n\n traverseFields({ callback, fields: collectionConfig.fields, ref: transformed })\n\n // Convert string ID to number if collection uses numeric custom ID\n const customIDType = payload.collections?.[collectionSlug]?.customIDType\n if (customIDType === 'number') {\n transformed.id = Number(transformed.id)\n }\n\n stripFields({\n config: payload.config,\n data: transformed,\n fields: flattenAllFields({ cache: true, fields: collectionConfig.fields }),\n reservedKeys: ['id', 'globalType'],\n })\n\n // Remove virtual fields - must happen AFTER stripFields\n removeVirtualFields(transformed, collectionConfig.fields)\n\n // Handle auth-specific fields that aren't in the field schema\n // When these fields are null in DB, Content API omits them from response (undefined)\n // But Payload expects them to be null, not undefined\n // Only add them if the collection has auth enabled\n if ('auth' in collectionConfig && collectionConfig.auth) {\n const authFields = ['resetPasswordExpiration', 'lockUntil']\n for (const fieldName of authFields) {\n if (!(fieldName in transformed)) {\n transformed[fieldName] = null\n }\n }\n }\n\n return transformed\n}\n"],"names":["flattenAllFields","traverseFields","applyDefaults","castFieldValue","removeVirtualFields","stripFields","dataToContentAPI","payload","collectionSlug","data","options","transformed","JSON","parse","stringify","isGlobal","startsWith","actualSlug","substring","collectionConfig","config","globals","find","g","slug","collections","c","fields","callback","field","ref","name","current","value","undefined","type","fillEmpty","cache","reservedKeys","customIDType","id","String","dataFromContentAPI","parentPath","isRequired","required","error","fieldPath","logger","warn","err","Error","msg","Number","auth","authFields","fieldName"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/db-content-api/utilities/data/index.ts"],"sourcesContent":["import type { CollectionConfig, GlobalConfig, Payload, TraverseFieldsCallback } from 'payload'\n\nimport { flattenAllFields, traverseFields } from 'payload'\n\nimport type { components } from '../../generated/content-api-types.js'\n\nimport { applyDefaults } from './applyDefaults.js'\nimport { castFieldValue } from './castFieldValue.js'\nimport { removeVirtualFields } from './removeVirtualFields.js'\nimport { stripFields } from './stripFields.js'\n\ntype DataWithOperations = components['schemas']['DataWithOperations']\n\n/**\n * Transform data before sending to Content API (WRITE operations)\n *\n * Conversions applied:\n * - Default values: Apply static defaults for undefined fields (when applyDefaults=true)\n * - Type casting: Convert values to match field types (e.g., number -> string for text fields)\n * - RichText fields: Objects -> JSON strings\n * - Virtual fields: Remove fields with `virtual: true` (pure virtual fields should never be saved)\n * - Timestamps: Add updatedAt (always), and createdAt (when createdAt=true)\n *\n * Note: Date fields are automatically converted to ISO strings by JSON.stringify()\n */\nexport function dataToContentAPI(\n payload: Payload,\n collectionSlug: string,\n data: unknown,\n options?: { applyDefaults?: boolean; createdAt?: boolean },\n): DataWithOperations {\n if (!data || typeof data !== 'object') {\n return data as DataWithOperations\n }\n\n // Deep clone to avoid mutating original data\n const transformed = JSON.parse(JSON.stringify(data))\n\n // Get collection config\n const isGlobal = collectionSlug.startsWith('_global-')\n const actualSlug = isGlobal ? collectionSlug.substring(8) : collectionSlug\n const collectionConfig: CollectionConfig | GlobalConfig | undefined = isGlobal\n ? payload.config.globals?.find((g) => g.slug === actualSlug)\n : payload.config.collections.find((c) => c.slug === actualSlug)\n\n if (!collectionConfig?.fields) {\n return transformed as DataWithOperations\n }\n\n // Apply static defaults recursively to handle nested structures (arrays, groups)\n // This must happen before traverseFields to ensure defaults are in place\n if (options?.applyDefaults) {\n applyDefaults(transformed, collectionConfig.fields)\n }\n\n // Use Payload's traverseFields to iterate over all fields for transformations\n const callback: TraverseFieldsCallback = ({ field, ref }) => {\n if (!('name' in field) || !field.name) {\n return\n }\n if (!ref || typeof ref !== 'object') {\n return\n }\n\n const current = ref as Record<string, unknown>\n let value = current[field.name]\n\n // Transform existing values\n if (value !== null && value !== undefined) {\n // Step 1: Apply type casting (e.g., number -> string for text fields)\n value = castFieldValue(field, value)\n current[field.name] = value\n\n // Step 2: Apply Content API specific transformations\n // RichText: object -> JSON string\n if (field.type === 'richText' && typeof value !== 'string') {\n current[field.name] = JSON.stringify(value)\n }\n // Date fields are already handled by JSON.stringify() which converts Date -> ISO string\n }\n }\n\n traverseFields({ callback, fields: collectionConfig.fields, fillEmpty: false, ref: transformed })\n\n stripFields({\n config: payload.config,\n data: transformed,\n fields: flattenAllFields({ cache: true, fields: collectionConfig.fields }),\n reservedKeys: ['id', 'globalType'],\n })\n\n removeVirtualFields(transformed, collectionConfig.fields)\n\n // Convert numeric ID to string for Content API\n const customIDType = payload.collections?.[collectionSlug]?.customIDType\n if (customIDType === 'number') {\n transformed.id = String(transformed.id)\n }\n\n // Add timestamps (Content API no longer auto-sets these in DB)\n // updatedAt is always set, createdAt only on create operations\n const now = new Date().toISOString()\n transformed.updatedAt = now\n if (options?.createdAt) {\n transformed.createdAt = now\n }\n\n return transformed as DataWithOperations\n}\n\n/**\n * Transform data received from Content API (READ operations)\n *\n * Conversions applied:\n * - RichText fields: JSON strings -> Objects\n * - Virtual fields: Remove fields with `virtual: true` (should not be in DB but Content API backend may add them)\n *\n * Note: Date fields come as ISO strings from Content API and stay as strings\n * (matching MongoDB and other adapters' behavior)\n */\nexport function dataFromContentAPI(\n payload: Payload,\n collectionSlug: string,\n data: unknown,\n): unknown {\n if (!data || typeof data !== 'object') {\n return data\n }\n\n // Deep clone to avoid mutating original data\n const transformed = JSON.parse(JSON.stringify(data))\n\n // Get collection config\n const isGlobal = collectionSlug.startsWith('_global-')\n const actualSlug = isGlobal ? collectionSlug.substring(8) : collectionSlug\n const collectionConfig: CollectionConfig | GlobalConfig | undefined = isGlobal\n ? payload.config.globals?.find((g) => g.slug === actualSlug)\n : payload.config.collections.find((c) => c.slug === actualSlug)\n\n if (!collectionConfig?.fields) {\n return transformed\n }\n\n // Use Payload's traverseFields to iterate over all fields\n const callback: TraverseFieldsCallback = ({ field, parentPath, ref }) => {\n if (!('name' in field) || !field.name) {\n return\n }\n if (!ref || typeof ref !== 'object') {\n return\n }\n\n const current = ref as Record<string, unknown>\n const value = current[field.name]\n\n // Normalize undefined → null for optional fields\n // Content API may omit fields (undefined) but Payload expects null for optional fields\n if (value === undefined) {\n const isRequired = 'required' in field && field.required\n if (!isRequired) {\n current[field.name] = null\n }\n return\n }\n\n if (value !== null) {\n // RichText: JSON string -> object\n if (field.type === 'richText' && typeof value === 'string') {\n try {\n current[field.name] = JSON.parse(value)\n } catch (error) {\n const fieldPath = parentPath ? `${parentPath}.${field.name}` : field.name\n payload.logger.warn({\n err: error instanceof Error ? error : new Error(String(error)),\n msg: `Failed to parse richtext field '${fieldPath}' in collection '${collectionSlug}'`,\n })\n }\n }\n // Date fields: Already ISO strings from Content API, no conversion needed\n }\n }\n\n traverseFields({ callback, fields: collectionConfig.fields, ref: transformed })\n\n // Convert string ID to number if collection uses numeric custom ID\n const customIDType = payload.collections?.[collectionSlug]?.customIDType\n if (customIDType === 'number') {\n transformed.id = Number(transformed.id)\n }\n\n stripFields({\n config: payload.config,\n data: transformed,\n fields: flattenAllFields({ cache: true, fields: collectionConfig.fields }),\n reservedKeys: ['id', 'globalType'],\n })\n\n // Remove virtual fields - must happen AFTER stripFields\n removeVirtualFields(transformed, collectionConfig.fields)\n\n // Handle auth-specific fields that aren't in the field schema\n // When these fields are null in DB, Content API omits them from response (undefined)\n // But Payload expects them to be null, not undefined\n // Only add them if the collection has auth enabled\n if ('auth' in collectionConfig && collectionConfig.auth) {\n const authFields = ['resetPasswordExpiration', 'lockUntil']\n for (const fieldName of authFields) {\n if (!(fieldName in transformed)) {\n transformed[fieldName] = null\n }\n }\n }\n\n return transformed\n}\n"],"names":["flattenAllFields","traverseFields","applyDefaults","castFieldValue","removeVirtualFields","stripFields","dataToContentAPI","payload","collectionSlug","data","options","transformed","JSON","parse","stringify","isGlobal","startsWith","actualSlug","substring","collectionConfig","config","globals","find","g","slug","collections","c","fields","callback","field","ref","name","current","value","undefined","type","fillEmpty","cache","reservedKeys","customIDType","id","String","now","Date","toISOString","updatedAt","createdAt","dataFromContentAPI","parentPath","isRequired","required","error","fieldPath","logger","warn","err","Error","msg","Number","auth","authFields","fieldName"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"where.d.ts","sourceRoot":"","sources":["../../../src/db-content-api/utilities/where.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAEpC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAA;AAEnE,KAAK,WAAW,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,aAAa,CAAC,CAAA;AASvD,KAAK,cAAc,GAAG;IACpB,yEAAyE;IACzE,qBAAqB,CAAC,EAAE,OAAO,CAAA;IAC/B,mFAAmF;IACnF,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAC7B,CAAA;AAED,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,SAAS,GAAG,KAAK,EACxB,OAAO,GAAE,cAAmB,GAC3B,WAAW,
|
|
1
|
+
{"version":3,"file":"where.d.ts","sourceRoot":"","sources":["../../../src/db-content-api/utilities/where.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAEpC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAA;AAEnE,KAAK,WAAW,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,aAAa,CAAC,CAAA;AASvD,KAAK,cAAc,GAAG;IACpB,yEAAyE;IACzE,qBAAqB,CAAC,EAAE,OAAO,CAAA;IAC/B,mFAAmF;IACnF,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAC7B,CAAA;AAED,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,SAAS,GAAG,KAAK,EACxB,OAAO,GAAE,cAAmB,GAC3B,WAAW,CA6Hb"}
|
|
@@ -70,6 +70,19 @@ export function convertPayloadWhereToContentAPI(where, options = {}) {
|
|
|
70
70
|
}
|
|
71
71
|
// Convert field conditions: { fieldName: { operator: value } }
|
|
72
72
|
// to: { path: fieldName, operator, value }
|
|
73
|
+
// Handle Payload's shorthand: { fieldName: value } → { fieldName: { equals: value } }
|
|
74
|
+
// If value is a primitive (string, number, boolean, null) or not a plain object,
|
|
75
|
+
// treat it as an implicit 'equals' operator
|
|
76
|
+
const isPrimitive = value === null || typeof value !== 'object' || Array.isArray(value);
|
|
77
|
+
if (isPrimitive) {
|
|
78
|
+
// Shorthand format: { id: "some-value" } means { id: { equals: "some-value" } }
|
|
79
|
+
conditions.push({
|
|
80
|
+
operator: 'equals',
|
|
81
|
+
path: fieldPath,
|
|
82
|
+
value
|
|
83
|
+
});
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
73
86
|
const operators = value;
|
|
74
87
|
// Skip empty operator objects { fieldName: {} }
|
|
75
88
|
if (Object.keys(operators).length === 0) {
|
|
@@ -82,9 +95,10 @@ export function convertPayloadWhereToContentAPI(where, options = {}) {
|
|
|
82
95
|
continue;
|
|
83
96
|
}
|
|
84
97
|
let finalValue = operatorValue;
|
|
85
|
-
//
|
|
86
|
-
|
|
87
|
-
|
|
98
|
+
// Convert string booleans to actual booleans for exists operator
|
|
99
|
+
// REST API sends "true"/"false" as strings, but Content API requires boolean
|
|
100
|
+
if (op === 'exists' && typeof operatorValue === 'string') {
|
|
101
|
+
finalValue = operatorValue === 'true';
|
|
88
102
|
}
|
|
89
103
|
conditions.push({
|
|
90
104
|
operator: op,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/db-content-api/utilities/where.ts"],"sourcesContent":["import type { Where } from 'payload'\n\nimport type { components } from '../generated/content-api-types.js'\n\ntype WhereClause = components['schemas']['WhereClause']\n\n// Payload's format: { fieldName: { operator: value }, and: [...], or: [...] }\n// Content API expects: { and: [{ path, operator, value }], or: [{ path, operator, value }] }\n//\n// The format stays different. This allows the Content API to evolve its filter schema,\n// for example to support composite types like Point, which are not lexicographically sortable.\n// Semantics must remain identical to Payload.\n\ntype ConvertOptions = {\n /** Internal flag to track if we're inside a logical operator (and/or) */\n insideLogicalOperator?: boolean\n /** If true, transform 'parent' field to 'documentId' (used for version queries) */\n parentToDocumentId?: boolean\n}\n\nexport function convertPayloadWhereToContentAPI(\n where: undefined | Where,\n options: ConvertOptions = {},\n): WhereClause {\n // Empty where {} should be { and: [] } not undefined\n // Content API requires a where clause structure even for \"no filter\"\n if (!where || Object.keys(where).length === 0) {\n return { and: [] }\n }\n\n // Extract the condition type (the variant with 'path', 'operator', 'value') from WhereClause union\n type WhereCondition = Extract<WhereClause, { path: string }>\n const conditions: WhereClause[] = []\n\n for (const [key, value] of Object.entries(where)) {\n if (key === 'and') {\n // Recursively convert nested 'and' conditions, preserving options\n const nestedConditions = (value as Where[])\n .map((item) =>\n convertPayloadWhereToContentAPI(item, { ...options, insideLogicalOperator: true }),\n )\n // TODO: A better solution would be to make the `where` schema of `zod` in `content-api`\n // more permissive. For now I'll do it this way because I have an idea to simplify\n // everything we're doing with `where` (Post EAP) anyway.\n // Filter out empty conditions { and: [] } that would be invalid\n .filter((condition) => {\n if ('and' in condition) {\n return condition.and.length > 0\n }\n if ('or' in condition) {\n return condition.or.length > 0\n }\n return true // Keep path/operator/value conditions\n })\n\n // If filtering resulted in no conditions, return empty and\n if (nestedConditions.length === 0) {\n return { and: [] }\n }\n\n return { and: nestedConditions }\n } else if (key === 'or') {\n // Recursively convert nested 'or' conditions, preserving options\n const nestedConditions = (value as Where[])\n .map((item) =>\n convertPayloadWhereToContentAPI(item, { ...options, insideLogicalOperator: true }),\n )\n // Filter out empty conditions { and: [] } or { or: [] } that would be invalid\n .filter((condition) => {\n if ('and' in condition) {\n return condition.and.length > 0\n }\n if ('or' in condition) {\n return condition.or.length > 0\n }\n return true // Keep path/operator/value conditions\n })\n\n // If filtering resulted in no conditions, return empty and\n if (nestedConditions.length === 0) {\n return { and: [] }\n }\n\n return { or: nestedConditions }\n } else {\n // TODO: fix this in content api\n // WORKAROUND: Payload uses 'parent' for version queries, but Content API expects 'documentId'\n let fieldPath = key\n if (options.parentToDocumentId && key === 'parent') {\n fieldPath = 'documentId'\n }\n\n // Convert field conditions: { fieldName: { operator: value } }\n // to: { path: fieldName, operator, value }\n const operators = value as Record<string, unknown>\n\n // Skip empty operator objects { fieldName: {} }\n if (Object.keys(operators).length === 0) {\n continue\n }\n\n for (const [op, operatorValue] of Object.entries(operators)) {\n // Skip operators with undefined values (e.g., { equals: undefined })\n // This can happen when Payload sends incomplete where clauses\n if (operatorValue === undefined) {\n continue\n }\n\n let finalValue = operatorValue\n\n //
|
|
1
|
+
{"version":3,"sources":["../../../src/db-content-api/utilities/where.ts"],"sourcesContent":["import type { Where } from 'payload'\n\nimport type { components } from '../generated/content-api-types.js'\n\ntype WhereClause = components['schemas']['WhereClause']\n\n// Payload's format: { fieldName: { operator: value }, and: [...], or: [...] }\n// Content API expects: { and: [{ path, operator, value }], or: [{ path, operator, value }] }\n//\n// The format stays different. This allows the Content API to evolve its filter schema,\n// for example to support composite types like Point, which are not lexicographically sortable.\n// Semantics must remain identical to Payload.\n\ntype ConvertOptions = {\n /** Internal flag to track if we're inside a logical operator (and/or) */\n insideLogicalOperator?: boolean\n /** If true, transform 'parent' field to 'documentId' (used for version queries) */\n parentToDocumentId?: boolean\n}\n\nexport function convertPayloadWhereToContentAPI(\n where: undefined | Where,\n options: ConvertOptions = {},\n): WhereClause {\n // Empty where {} should be { and: [] } not undefined\n // Content API requires a where clause structure even for \"no filter\"\n if (!where || Object.keys(where).length === 0) {\n return { and: [] }\n }\n\n // Extract the condition type (the variant with 'path', 'operator', 'value') from WhereClause union\n type WhereCondition = Extract<WhereClause, { path: string }>\n const conditions: WhereClause[] = []\n\n for (const [key, value] of Object.entries(where)) {\n if (key === 'and') {\n // Recursively convert nested 'and' conditions, preserving options\n const nestedConditions = (value as Where[])\n .map((item) =>\n convertPayloadWhereToContentAPI(item, { ...options, insideLogicalOperator: true }),\n )\n // TODO: A better solution would be to make the `where` schema of `zod` in `content-api`\n // more permissive. For now I'll do it this way because I have an idea to simplify\n // everything we're doing with `where` (Post EAP) anyway.\n // Filter out empty conditions { and: [] } that would be invalid\n .filter((condition) => {\n if ('and' in condition) {\n return condition.and.length > 0\n }\n if ('or' in condition) {\n return condition.or.length > 0\n }\n return true // Keep path/operator/value conditions\n })\n\n // If filtering resulted in no conditions, return empty and\n if (nestedConditions.length === 0) {\n return { and: [] }\n }\n\n return { and: nestedConditions }\n } else if (key === 'or') {\n // Recursively convert nested 'or' conditions, preserving options\n const nestedConditions = (value as Where[])\n .map((item) =>\n convertPayloadWhereToContentAPI(item, { ...options, insideLogicalOperator: true }),\n )\n // Filter out empty conditions { and: [] } or { or: [] } that would be invalid\n .filter((condition) => {\n if ('and' in condition) {\n return condition.and.length > 0\n }\n if ('or' in condition) {\n return condition.or.length > 0\n }\n return true // Keep path/operator/value conditions\n })\n\n // If filtering resulted in no conditions, return empty and\n if (nestedConditions.length === 0) {\n return { and: [] }\n }\n\n return { or: nestedConditions }\n } else {\n // TODO: fix this in content api\n // WORKAROUND: Payload uses 'parent' for version queries, but Content API expects 'documentId'\n let fieldPath = key\n if (options.parentToDocumentId && key === 'parent') {\n fieldPath = 'documentId'\n }\n\n // Convert field conditions: { fieldName: { operator: value } }\n // to: { path: fieldName, operator, value }\n\n // Handle Payload's shorthand: { fieldName: value } → { fieldName: { equals: value } }\n // If value is a primitive (string, number, boolean, null) or not a plain object,\n // treat it as an implicit 'equals' operator\n const isPrimitive = value === null || typeof value !== 'object' || Array.isArray(value)\n\n if (isPrimitive) {\n // Shorthand format: { id: \"some-value\" } means { id: { equals: \"some-value\" } }\n conditions.push({\n operator: 'equals',\n path: fieldPath,\n value,\n } as WhereCondition)\n continue\n }\n\n const operators = value as Record<string, unknown>\n\n // Skip empty operator objects { fieldName: {} }\n if (Object.keys(operators).length === 0) {\n continue\n }\n\n for (const [op, operatorValue] of Object.entries(operators)) {\n // Skip operators with undefined values (e.g., { equals: undefined })\n // This can happen when Payload sends incomplete where clauses\n if (operatorValue === undefined) {\n continue\n }\n\n let finalValue = operatorValue\n\n // Convert string booleans to actual booleans for exists operator\n // REST API sends \"true\"/\"false\" as strings, but Content API requires boolean\n if (op === 'exists' && typeof operatorValue === 'string') {\n finalValue = operatorValue === 'true'\n }\n\n conditions.push({\n operator: op as WhereCondition['operator'],\n path: fieldPath,\n value: finalValue,\n } as WhereCondition)\n }\n }\n }\n\n // If inside a logical operator (and/or), return conditions directly\n // Otherwise, wrap in 'and' to match WhereClause type\n if (options.insideLogicalOperator && conditions.length === 1) {\n return conditions[0]\n }\n\n return { and: conditions }\n}\n"],"names":["convertPayloadWhereToContentAPI","where","options","Object","keys","length","and","conditions","key","value","entries","nestedConditions","map","item","insideLogicalOperator","filter","condition","or","fieldPath","parentToDocumentId","isPrimitive","Array","isArray","push","operator","path","operators","op","operatorValue","undefined","finalValue"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/oauth/components/LogoutButton/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/oauth/components/LogoutButton/index.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,cAAc,CAAA;AAIrB,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CA6D/E,CAAA"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { Logout, useConfig } from '@payloadcms/ui';
|
|
4
|
+
import { formatAdminURL } from 'payload/shared';
|
|
4
5
|
import React from 'react';
|
|
5
|
-
import { getAdminPath } from '../../utilities/getAdminPath.js';
|
|
6
6
|
import './index.scss';
|
|
7
7
|
const baseClass = 'oauth-logout';
|
|
8
8
|
export const LogoutButton = ({ disabled, endpointSlug })=>{
|
|
@@ -16,8 +16,10 @@ export const LogoutButton = ({ disabled, endpointSlug })=>{
|
|
|
16
16
|
if (port) {
|
|
17
17
|
redirectToSet += `:${port}`;
|
|
18
18
|
}
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
setRedirect(formatAdminURL({
|
|
20
|
+
adminRoute: config.routes.admin,
|
|
21
|
+
serverURL: redirectToSet
|
|
22
|
+
}));
|
|
21
23
|
}, [
|
|
22
24
|
config
|
|
23
25
|
]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/oauth/components/LogoutButton/index.tsx"],"sourcesContent":["'use client'\n\nimport { Logout, useConfig } from '@payloadcms/ui'\nimport
|
|
1
|
+
{"version":3,"sources":["../../../../src/oauth/components/LogoutButton/index.tsx"],"sourcesContent":["'use client'\n\nimport { Logout, useConfig } from '@payloadcms/ui'\nimport { formatAdminURL } from 'payload/shared'\nimport React from 'react'\n\nimport './index.scss'\n\nconst baseClass = 'oauth-logout'\n\nexport const LogoutButton: React.FC<{ disabled?: boolean; endpointSlug: string }> = ({\n disabled,\n endpointSlug,\n}) => {\n const {\n config,\n config: {\n admin: { user: userSlug },\n routes: { api },\n serverURL,\n },\n } = useConfig()\n\n const [redirect, setRedirect] = React.useState('')\n React.useEffect(() => {\n const protocol = window.location.protocol\n const domain = window.location.hostname\n const port = window.location.port\n\n let redirectToSet = `${protocol}//${domain}`\n if (port) {\n redirectToSet += `:${port}`\n }\n\n setRedirect(\n formatAdminURL({\n adminRoute: config.routes.admin,\n serverURL: redirectToSet,\n }),\n )\n }, [config])\n\n if (!redirect) {\n return null\n }\n\n if (disabled) {\n return <Logout />\n }\n\n return (\n <div className={baseClass}>\n <a\n aria-label=\"Logout\"\n href={`${serverURL}${api}/${userSlug}/${endpointSlug}/logout?redirect=${redirect}`}\n >\n <svg\n className=\"icon icon--logout\"\n fill=\"none\"\n viewBox=\"0 0 25 25\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path className=\"stroke\" d=\"M10 5H18V19H10\" />\n <g>\n <path className=\"stroke\" d=\"M8 8.5L4.46447 12.0355L8 15.5711\" />\n <line className=\"stroke\" x1=\"5\" x2=\"13\" y1=\"12\" y2=\"12\" />\n </g>\n </svg>\n </a>\n </div>\n )\n}\n"],"names":["Logout","useConfig","formatAdminURL","React","baseClass","LogoutButton","disabled","endpointSlug","config","admin","user","userSlug","routes","api","serverURL","redirect","setRedirect","useState","useEffect","protocol","window","location","domain","hostname","port","redirectToSet","adminRoute","div","className","a","aria-label","href","svg","fill","viewBox","xmlns","path","d","g","line","x1","x2","y1","y2"],"mappings":"AAAA;;AAEA,SAASA,MAAM,EAAEC,SAAS,QAAQ,iBAAgB;AAClD,SAASC,cAAc,QAAQ,iBAAgB;AAC/C,OAAOC,WAAW,QAAO;AAEzB,OAAO,eAAc;AAErB,MAAMC,YAAY;AAElB,OAAO,MAAMC,eAAuE,CAAC,EACnFC,QAAQ,EACRC,YAAY,EACb;IACC,MAAM,EACJC,MAAM,EACNA,QAAQ,EACNC,OAAO,EAAEC,MAAMC,QAAQ,EAAE,EACzBC,QAAQ,EAAEC,GAAG,EAAE,EACfC,SAAS,EACV,EACF,GAAGb;IAEJ,MAAM,CAACc,UAAUC,YAAY,GAAGb,MAAMc,QAAQ,CAAC;IAC/Cd,MAAMe,SAAS,CAAC;QACd,MAAMC,WAAWC,OAAOC,QAAQ,CAACF,QAAQ;QACzC,MAAMG,SAASF,OAAOC,QAAQ,CAACE,QAAQ;QACvC,MAAMC,OAAOJ,OAAOC,QAAQ,CAACG,IAAI;QAEjC,IAAIC,gBAAgB,GAAGN,SAAS,EAAE,EAAEG,QAAQ;QAC5C,IAAIE,MAAM;YACRC,iBAAiB,CAAC,CAAC,EAAED,MAAM;QAC7B;QAEAR,YACEd,eAAe;YACbwB,YAAYlB,OAAOI,MAAM,CAACH,KAAK;YAC/BK,WAAWW;QACb;IAEJ,GAAG;QAACjB;KAAO;IAEX,IAAI,CAACO,UAAU;QACb,OAAO;IACT;IAEA,IAAIT,UAAU;QACZ,qBAAO,KAACN;IACV;IAEA,qBACE,KAAC2B;QAAIC,WAAWxB;kBACd,cAAA,KAACyB;YACCC,cAAW;YACXC,MAAM,GAAGjB,YAAYD,IAAI,CAAC,EAAEF,SAAS,CAAC,EAAEJ,aAAa,iBAAiB,EAAEQ,UAAU;sBAElF,cAAA,MAACiB;gBACCJ,WAAU;gBACVK,MAAK;gBACLC,SAAQ;gBACRC,OAAM;;kCAEN,KAACC;wBAAKR,WAAU;wBAASS,GAAE;;kCAC3B,MAACC;;0CACC,KAACF;gCAAKR,WAAU;gCAASS,GAAE;;0CAC3B,KAACE;gCAAKX,WAAU;gCAASY,IAAG;gCAAIC,IAAG;gCAAKC,IAAG;gCAAKC,IAAG;;;;;;;;AAM/D,EAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getLoginEndpoint.d.ts","sourceRoot":"","sources":["../../../src/oauth/endpoints/getLoginEndpoint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAKzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAY,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"getLoginEndpoint.d.ts","sourceRoot":"","sources":["../../../src/oauth/endpoints/getLoginEndpoint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAKzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAY,MAAM,aAAa,CAAA;AAQ7E,UAAU,IAAI;IACZ,UAAU,EAAE,gBAAgB,CAAA;IAC5B,iBAAiB,EAAE,iBAAiB,CAAA;IACpC,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,aAAa,CAAA;IAC5B,QAAQ,EAAE,QAAQ,CAAA;CACnB;AAID,eAAO,MAAM,gBAAgB,8EAM1B,IAAI,KAAG,QA4PR,CAAA"}
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import { APIError, generateCookie, parseCookies } from 'payload';
|
|
2
|
-
import { getSafeRedirect } from 'payload/shared';
|
|
2
|
+
import { formatAdminURL, getSafeRedirect } from 'payload/shared';
|
|
3
3
|
import { getProjectToken } from '../../api/figma-api.js';
|
|
4
4
|
import { createCookieOptions } from '../utilities/createCookieOptions.js';
|
|
5
5
|
import { createDebugLogger } from '../utilities/createDebugLogger.js';
|
|
6
6
|
import { extractOrigin } from '../utilities/extractOrigin.js';
|
|
7
|
-
import { getAdminPath } from '../utilities/getAdminPath.js';
|
|
8
7
|
import { getCookieExpiration } from '../utilities/getCookieExpiration.js';
|
|
9
8
|
const isAbsoluteURL = (url)=>/^[a-z][a-z\d+.-]*:/.test(url);
|
|
10
9
|
export const getLoginEndpoint = ({ collection, collectionOptions, endpointSlug, pluginOptions, strategy })=>({
|
|
11
10
|
handler: async (req)=>{
|
|
12
11
|
const { config } = req.payload;
|
|
13
|
-
const
|
|
12
|
+
const adminRoute = config.routes?.admin || '/admin';
|
|
14
13
|
try {
|
|
15
14
|
await strategy.ensureMeta();
|
|
16
15
|
const path = req.pathname;
|
|
@@ -37,9 +36,16 @@ export const getLoginEndpoint = ({ collection, collectionOptions, endpointSlug,
|
|
|
37
36
|
}
|
|
38
37
|
const stateRaw = jsonBody.state;
|
|
39
38
|
const state = JSON.parse(Buffer.from(stateRaw, 'base64').toString('utf-8'));
|
|
40
|
-
const
|
|
41
|
-
let failedRedirect =
|
|
42
|
-
|
|
39
|
+
const redirectServerURL = state.serverURL || pluginOptions.redirectServerURL || config.serverURL;
|
|
40
|
+
let failedRedirect = formatAdminURL({
|
|
41
|
+
adminRoute,
|
|
42
|
+
path: '/login',
|
|
43
|
+
serverURL: redirectServerURL
|
|
44
|
+
});
|
|
45
|
+
let redirectToUse = formatAdminURL({
|
|
46
|
+
adminRoute,
|
|
47
|
+
serverURL: redirectServerURL
|
|
48
|
+
});
|
|
43
49
|
if (state.redirect) {
|
|
44
50
|
redirectToUse = state.redirect;
|
|
45
51
|
}
|
|
@@ -126,7 +132,11 @@ export const getLoginEndpoint = ({ collection, collectionOptions, endpointSlug,
|
|
|
126
132
|
code,
|
|
127
133
|
code_verifier: req.payload.decrypt(state.verifier),
|
|
128
134
|
grant_type: 'authorization_code',
|
|
129
|
-
redirect_uri:
|
|
135
|
+
redirect_uri: formatAdminURL({
|
|
136
|
+
apiRoute: config.routes?.api || '/api',
|
|
137
|
+
path: `/${collection.slug}/${endpointSlug}/login`,
|
|
138
|
+
serverURL: redirectServerURL
|
|
139
|
+
})
|
|
130
140
|
};
|
|
131
141
|
if (strategy.collectionOptions.clientSecret) {
|
|
132
142
|
body.client_secret = strategy.collectionOptions.clientSecret;
|