@seshuk/payload-plugin-openapi 0.1.0 → 0.2.1
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/README.md +55 -539
- package/dist/index.d.ts +1 -1
- package/dist/options.js +1 -0
- package/dist/spec/buildDocument.js +39 -5
- package/dist/spec/components.d.ts +0 -2
- package/dist/spec/components.js +1 -16
- package/dist/spec/downconvert.d.ts +1 -1
- package/dist/spec/downconvert.js +27 -8
- package/dist/spec/entitySchemas.js +36 -32
- package/dist/spec/filters.js +12 -3
- package/dist/spec/params.d.ts +9 -1
- package/dist/spec/params.js +93 -1
- package/dist/spec/paths/auth.js +52 -63
- package/dist/spec/paths/collections.d.ts +3 -1
- package/dist/spec/paths/collections.js +42 -25
- package/dist/spec/paths/globals.d.ts +3 -1
- package/dist/spec/paths/globals.js +23 -13
- package/dist/spec/paths/versions.d.ts +2 -1
- package/dist/spec/paths/versions.js +14 -5
- package/dist/spec/security.d.ts +19 -0
- package/dist/spec/security.js +96 -0
- package/dist/translations/locales/ar.js +5 -0
- package/dist/translations/locales/az.js +5 -0
- package/dist/translations/locales/bg.js +5 -0
- package/dist/translations/locales/bnBd.js +5 -0
- package/dist/translations/locales/bnIn.js +5 -0
- package/dist/translations/locales/ca.js +5 -0
- package/dist/translations/locales/cs.js +5 -0
- package/dist/translations/locales/da.js +5 -0
- package/dist/translations/locales/de.js +5 -0
- package/dist/translations/locales/en.js +5 -0
- package/dist/translations/locales/es.js +5 -0
- package/dist/translations/locales/et.js +5 -0
- package/dist/translations/locales/fa.js +5 -0
- package/dist/translations/locales/fr.js +5 -0
- package/dist/translations/locales/he.js +5 -0
- package/dist/translations/locales/hr.js +5 -0
- package/dist/translations/locales/hu.js +5 -0
- package/dist/translations/locales/hy.js +5 -0
- package/dist/translations/locales/id.js +5 -0
- package/dist/translations/locales/is.js +5 -0
- package/dist/translations/locales/it.js +5 -0
- package/dist/translations/locales/ja.js +5 -0
- package/dist/translations/locales/ko.js +5 -0
- package/dist/translations/locales/lt.js +5 -0
- package/dist/translations/locales/lv.js +5 -0
- package/dist/translations/locales/my.js +5 -0
- package/dist/translations/locales/nb.js +5 -0
- package/dist/translations/locales/nl.js +5 -0
- package/dist/translations/locales/pl.js +5 -0
- package/dist/translations/locales/pt.js +5 -0
- package/dist/translations/locales/ro.js +5 -0
- package/dist/translations/locales/rs.js +5 -0
- package/dist/translations/locales/rsLatin.js +5 -0
- package/dist/translations/locales/ru.js +5 -0
- package/dist/translations/locales/sk.js +5 -0
- package/dist/translations/locales/sl.js +5 -0
- package/dist/translations/locales/sv.js +5 -0
- package/dist/translations/locales/ta.js +5 -0
- package/dist/translations/locales/th.js +5 -0
- package/dist/translations/locales/tr.js +5 -0
- package/dist/translations/locales/uk.js +5 -0
- package/dist/translations/locales/vi.js +5 -0
- package/dist/translations/locales/zh.js +5 -0
- package/dist/translations/locales/zhTw.js +5 -0
- package/dist/translations/types.d.ts +5 -0
- package/dist/types.d.ts +9 -0
- package/package.json +39 -24
package/dist/options.js
CHANGED
|
@@ -37,6 +37,7 @@ const resolveOptions = (options)=>{
|
|
|
37
37
|
filters: resolveFilters(options.filters),
|
|
38
38
|
interactiveAuth: resolveInteractiveAuth(options.interactiveAuth),
|
|
39
39
|
nestedTags: options.nestedTags ?? false,
|
|
40
|
+
securityWhen: options.securityWhen,
|
|
40
41
|
cache: options.cache ?? true,
|
|
41
42
|
extensions: options.extensions ?? []
|
|
42
43
|
};
|
|
@@ -7,6 +7,7 @@ import { buildBlockSchema, buildEntitySchemas } from "./entitySchemas.js";
|
|
|
7
7
|
import { filterOperations, shouldIncludeCollection, shouldIncludeGlobal } from "./filters.js";
|
|
8
8
|
import { blockSchemaName, createSchemaName, globalSchemaName, joinsSchemaName, listSchemaName, populateSchemaName, querySchemaName, schemaName, selectSchemaName, updateSchemaName } from "./names.js";
|
|
9
9
|
import { buildParamSchemas, buildQueryOperationsSchema, collectionHasFilters } from "./params.js";
|
|
10
|
+
import { applySecurityWhen, resolveEntitySecurity } from "./security.js";
|
|
10
11
|
import { buildTagHierarchy } from "./tags.js";
|
|
11
12
|
import { buildAuthPaths } from "./paths/auth.js";
|
|
12
13
|
import { buildCollectionPaths } from "./paths/collections.js";
|
|
@@ -66,10 +67,21 @@ const buildDocument = async (input)=>{
|
|
|
66
67
|
ctx
|
|
67
68
|
});
|
|
68
69
|
registerParamSchemas(schemas, base, collection.fields, ctx);
|
|
70
|
+
const security = await resolveEntitySecurity({
|
|
71
|
+
entity: collection,
|
|
72
|
+
operations: [
|
|
73
|
+
'read',
|
|
74
|
+
'create',
|
|
75
|
+
'update',
|
|
76
|
+
'delete'
|
|
77
|
+
],
|
|
78
|
+
locale: ctx.locales[0]
|
|
79
|
+
});
|
|
69
80
|
const collectionPaths = {
|
|
70
81
|
...buildCollectionPaths({
|
|
71
82
|
collection,
|
|
72
|
-
ctx
|
|
83
|
+
ctx,
|
|
84
|
+
security
|
|
73
85
|
})
|
|
74
86
|
};
|
|
75
87
|
if (filters.includeAuth) Object.assign(collectionPaths, buildAuthPaths({
|
|
@@ -94,11 +106,17 @@ const buildDocument = async (input)=>{
|
|
|
94
106
|
nestedTags: options.nestedTags
|
|
95
107
|
}));
|
|
96
108
|
}
|
|
97
|
-
|
|
109
|
+
const filteredCollectionPaths = filterOperations({
|
|
98
110
|
paths: collectionPaths,
|
|
99
111
|
slug: collection.slug,
|
|
100
112
|
kind: 'collection',
|
|
101
113
|
filters
|
|
114
|
+
});
|
|
115
|
+
Object.assign(paths, applySecurityWhen({
|
|
116
|
+
paths: filteredCollectionPaths,
|
|
117
|
+
slug: collection.slug,
|
|
118
|
+
kind: 'collection',
|
|
119
|
+
securityWhen: options.securityWhen
|
|
102
120
|
}));
|
|
103
121
|
} catch (error) {
|
|
104
122
|
logger.warn(`${PLUGIN_NAME}: skipped collection "${collection.slug}": ${error.message}`);
|
|
@@ -118,10 +136,19 @@ const buildDocument = async (input)=>{
|
|
|
118
136
|
schemas[gbase] = read;
|
|
119
137
|
schemas[updateSchemaName(gbase)] = update;
|
|
120
138
|
registerParamSchemas(schemas, gbase, global.fields, ctx);
|
|
139
|
+
const security = await resolveEntitySecurity({
|
|
140
|
+
entity: global,
|
|
141
|
+
operations: [
|
|
142
|
+
'read',
|
|
143
|
+
'update'
|
|
144
|
+
],
|
|
145
|
+
locale: ctx.locales[0]
|
|
146
|
+
});
|
|
121
147
|
const globalPaths = {
|
|
122
148
|
...buildGlobalPaths({
|
|
123
149
|
global,
|
|
124
|
-
ctx
|
|
150
|
+
ctx,
|
|
151
|
+
security
|
|
125
152
|
})
|
|
126
153
|
};
|
|
127
154
|
if (filters.includeVersions && global.versions) {
|
|
@@ -137,14 +164,21 @@ const buildDocument = async (input)=>{
|
|
|
137
164
|
pathBase: `${ctx.apiRoute}/globals/${global.slug}`,
|
|
138
165
|
ctx,
|
|
139
166
|
schemaBase: gbase,
|
|
140
|
-
nestedTags: options.nestedTags
|
|
167
|
+
nestedTags: options.nestedTags,
|
|
168
|
+
global: true
|
|
141
169
|
}));
|
|
142
170
|
}
|
|
143
|
-
|
|
171
|
+
const filteredGlobalPaths = filterOperations({
|
|
144
172
|
paths: globalPaths,
|
|
145
173
|
slug: global.slug,
|
|
146
174
|
kind: 'global',
|
|
147
175
|
filters
|
|
176
|
+
});
|
|
177
|
+
Object.assign(paths, applySecurityWhen({
|
|
178
|
+
paths: filteredGlobalPaths,
|
|
179
|
+
slug: global.slug,
|
|
180
|
+
kind: 'global',
|
|
181
|
+
securityWhen: options.securityWhen
|
|
148
182
|
}));
|
|
149
183
|
} catch (error) {
|
|
150
184
|
logger.warn(`${PLUGIN_NAME}: skipped global "${global.slug}": ${error.message}`);
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { Access } from 'payload';
|
|
2
1
|
import type { ReferenceObject, RequestBodyObject, ResponseObject, ResponsesObject, SchemaObject, SecuritySchemeObject } from '@scalar/openapi-types/3.2';
|
|
3
2
|
import type { Translate } from '../translations/types.js';
|
|
4
3
|
type SchemaOrRef = SchemaObject | ReferenceObject;
|
|
@@ -42,5 +41,4 @@ export declare const securityScheme: ({ cookiePrefix, t }: {
|
|
|
42
41
|
cookiePrefix: string;
|
|
43
42
|
t: Translate;
|
|
44
43
|
}) => SecuritySchemeObject;
|
|
45
|
-
export declare const isOpenToPublic: (access: Access | undefined) => boolean;
|
|
46
44
|
export {};
|
package/dist/spec/components.js
CHANGED
|
@@ -262,19 +262,4 @@ const securityScheme = ({ cookiePrefix, t })=>({
|
|
|
262
262
|
cookiePrefix
|
|
263
263
|
})
|
|
264
264
|
});
|
|
265
|
-
|
|
266
|
-
if (!access) return true;
|
|
267
|
-
const trap = new Proxy({}, {
|
|
268
|
-
get () {
|
|
269
|
-
throw new Error('req accessed');
|
|
270
|
-
}
|
|
271
|
-
});
|
|
272
|
-
try {
|
|
273
|
-
return true === access({
|
|
274
|
-
req: trap
|
|
275
|
-
});
|
|
276
|
-
} catch {
|
|
277
|
-
return false;
|
|
278
|
-
}
|
|
279
|
-
};
|
|
280
|
-
export { ERRORS, ERROR_SCHEMA_NAME, INTERACTIVE_SCHEME_NAME, SECURITY_SCHEME_NAME, buildErrorResponseSchema, buildListEnvelopeSchema, errorResponses, interactiveSecurityScheme, isOpenToPublic, jsonBody, jsonOk, jsonResponse, messageResponse, nullableType, securityScheme, uploadRequestBody };
|
|
265
|
+
export { ERRORS, ERROR_SCHEMA_NAME, INTERACTIVE_SCHEME_NAME, SECURITY_SCHEME_NAME, buildErrorResponseSchema, buildListEnvelopeSchema, errorResponses, interactiveSecurityScheme, jsonBody, jsonOk, jsonResponse, messageResponse, nullableType, securityScheme, uploadRequestBody };
|
package/dist/spec/downconvert.js
CHANGED
|
@@ -23,9 +23,27 @@ const downconvertTo30 = (node)=>{
|
|
|
23
23
|
}
|
|
24
24
|
if (Array.isArray(out.type)) {
|
|
25
25
|
const types = out.type;
|
|
26
|
-
|
|
26
|
+
const nullable = types.includes(NULL);
|
|
27
27
|
const rest = types.filter((t)=>t !== NULL);
|
|
28
|
-
|
|
28
|
+
if (1 === rest.length) {
|
|
29
|
+
out.type = rest[0];
|
|
30
|
+
if (nullable) out.nullable = true;
|
|
31
|
+
} else if (rest.length > 1) {
|
|
32
|
+
delete out.type;
|
|
33
|
+
const union = rest.map((type)=>nullable ? {
|
|
34
|
+
type,
|
|
35
|
+
nullable: true
|
|
36
|
+
} : {
|
|
37
|
+
type
|
|
38
|
+
});
|
|
39
|
+
if (out.anyOf) out.allOf = [
|
|
40
|
+
...out.allOf ?? [],
|
|
41
|
+
{
|
|
42
|
+
anyOf: union
|
|
43
|
+
}
|
|
44
|
+
];
|
|
45
|
+
else out.anyOf = union;
|
|
46
|
+
}
|
|
29
47
|
}
|
|
30
48
|
if ('const' in out) {
|
|
31
49
|
out.enum = [
|
|
@@ -39,17 +57,18 @@ const downconvertTo30 = (node)=>{
|
|
|
39
57
|
if (examples.length > 1) out['x-examples'] = examples;
|
|
40
58
|
delete out.examples;
|
|
41
59
|
}
|
|
60
|
+
if (Array.isArray(out.required) && 0 === out.required.length) delete out.required;
|
|
42
61
|
for (const keyword of UNSUPPORTED_KEYWORDS)delete out[keyword];
|
|
43
62
|
return out;
|
|
44
63
|
};
|
|
45
|
-
const toOpenApi30 = (doc)=>{
|
|
46
|
-
const converted = downconvertTo30(doc);
|
|
47
|
-
converted.openapi = '3.0.4';
|
|
48
|
-
return converted;
|
|
49
|
-
};
|
|
50
64
|
const toOpenApi31 = (doc)=>({
|
|
51
65
|
...doc,
|
|
52
66
|
openapi: '3.1.2',
|
|
53
|
-
tags: doc.tags?.map(({ kind: _kind, parent: _parent, ...rest })=>rest)
|
|
67
|
+
tags: doc.tags?.map(({ kind: _kind, parent: _parent, summary: _summary, ...rest })=>rest)
|
|
54
68
|
});
|
|
69
|
+
const toOpenApi30 = (doc)=>{
|
|
70
|
+
const converted = downconvertTo30(toOpenApi31(doc));
|
|
71
|
+
converted.openapi = '3.0.4';
|
|
72
|
+
return converted;
|
|
73
|
+
};
|
|
55
74
|
export { toOpenApi30, toOpenApi31 };
|
|
@@ -3,7 +3,7 @@ import { getTranslation } from "@payloadcms/translations";
|
|
|
3
3
|
import { deepMerge, isPlainObject } from "../utils.js";
|
|
4
4
|
import { makeT } from "../translations/index.js";
|
|
5
5
|
import { AUTH_FIELDS, flattenFields } from "./fields.js";
|
|
6
|
-
import { rewriteRefs } from "./names.js";
|
|
6
|
+
import { refTo, rewriteRefs, schemaName } from "./names.js";
|
|
7
7
|
const READ_HIDDEN_FIELDS = new Set([
|
|
8
8
|
...AUTH_FIELDS,
|
|
9
9
|
'collection'
|
|
@@ -17,8 +17,10 @@ const stripInterfaceName = (entity)=>{
|
|
|
17
17
|
const { interfaceName: _omit, ...rest } = entity;
|
|
18
18
|
return rest;
|
|
19
19
|
};
|
|
20
|
-
const toComponentSchema = ({ config, source, idType })=>{
|
|
21
|
-
const jsonSchema = entityToJSONSchema(config, source, new Map(), idType
|
|
20
|
+
const toComponentSchema = ({ config, source, idType, write = false })=>{
|
|
21
|
+
const jsonSchema = entityToJSONSchema(config, source, new Map(), idType, void 0, void 0, {
|
|
22
|
+
forceInlineBlocks: write
|
|
23
|
+
});
|
|
22
24
|
const blockSlugs = new Set((config.blocks ?? []).map((b)=>b.slug));
|
|
23
25
|
const schema = rewriteRefs(jsonSchema, blockSlugs);
|
|
24
26
|
delete schema.title;
|
|
@@ -124,12 +126,33 @@ const removeProps = (schema, names)=>{
|
|
|
124
126
|
schema.required = schema.required.filter((r)=>!drop.has(r));
|
|
125
127
|
}
|
|
126
128
|
};
|
|
127
|
-
const
|
|
129
|
+
const toIdType = (type)=>Array.isArray(type) ? type.map(toIdType) : 'number' === type ? 'integer' : type;
|
|
130
|
+
const writeRelationshipsAsIds = (node, refs)=>{
|
|
131
|
+
if (Array.isArray(node)) {
|
|
132
|
+
for (const item of node)writeRelationshipsAsIds(item, refs);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
if (!isPlainObject(node)) return;
|
|
136
|
+
const oneOf = node.oneOf;
|
|
137
|
+
if (Array.isArray(oneOf) && 2 === oneOf.length && isRef(oneOf[1]) && refs.has(oneOf[1].$ref)) {
|
|
138
|
+
delete node.oneOf;
|
|
139
|
+
node.type = toIdType(oneOf[0].type);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
for (const value of Object.values(node))writeRelationshipsAsIds(value, refs);
|
|
143
|
+
};
|
|
144
|
+
const buildBaseSchema = ({ entity, config, ctx, write = false })=>{
|
|
145
|
+
const idType = ctx.defaultIDType;
|
|
128
146
|
const schema = toComponentSchema({
|
|
129
147
|
config,
|
|
130
148
|
source: stripInterfaceName(entity),
|
|
131
|
-
idType
|
|
149
|
+
idType,
|
|
150
|
+
write
|
|
132
151
|
});
|
|
152
|
+
if (write) {
|
|
153
|
+
const refs = new Set((config.collections ?? []).map((c)=>refTo(schemaName(c.slug))));
|
|
154
|
+
writeRelationshipsAsIds(schema, refs);
|
|
155
|
+
}
|
|
133
156
|
const isAuth = 'auth' in entity && Boolean(entity.auth);
|
|
134
157
|
if (isAuth) removeProps(schema, READ_HIDDEN_FIELDS);
|
|
135
158
|
applyFieldOverrides({
|
|
@@ -149,38 +172,24 @@ const cloneSchema = (schema)=>({
|
|
|
149
172
|
...schema.required
|
|
150
173
|
] : schema.required
|
|
151
174
|
});
|
|
152
|
-
const flattenRelationships = ({ schema, fields, idType })=>{
|
|
153
|
-
if (!schema.properties) return;
|
|
154
|
-
const idSchema = {
|
|
155
|
-
type: 'number' === idType ? 'integer' : 'string'
|
|
156
|
-
};
|
|
157
|
-
for (const field of flattenFields(fields)){
|
|
158
|
-
if ('relationship' !== field.type && 'upload' !== field.type) continue;
|
|
159
|
-
const name = 'name' in field ? field.name : void 0;
|
|
160
|
-
if (name && name in schema.properties) schema.properties[name] = 'hasMany' in field && field.hasMany ? {
|
|
161
|
-
type: 'array',
|
|
162
|
-
items: idSchema
|
|
163
|
-
} : idSchema;
|
|
164
|
-
}
|
|
165
|
-
};
|
|
166
175
|
const buildEntitySchemas = async ({ entity, config, ctx })=>{
|
|
167
176
|
const read = buildBaseSchema({
|
|
168
177
|
entity,
|
|
169
178
|
config,
|
|
170
179
|
ctx
|
|
171
180
|
});
|
|
181
|
+
const write = buildBaseSchema({
|
|
182
|
+
entity,
|
|
183
|
+
config,
|
|
184
|
+
ctx,
|
|
185
|
+
write: true
|
|
186
|
+
});
|
|
172
187
|
const isAuth = 'auth' in entity && Boolean(entity.auth);
|
|
173
|
-
const
|
|
174
|
-
const create = cloneSchema(read);
|
|
188
|
+
const create = cloneSchema(write);
|
|
175
189
|
if (Array.isArray(create.required)) {
|
|
176
190
|
const optional = new Set(SERVER_FIELDS);
|
|
177
191
|
create.required = create.required.filter((r)=>!optional.has(r));
|
|
178
192
|
}
|
|
179
|
-
flattenRelationships({
|
|
180
|
-
schema: create,
|
|
181
|
-
fields: entity.fields,
|
|
182
|
-
idType
|
|
183
|
-
});
|
|
184
193
|
if (isAuth && create.properties) {
|
|
185
194
|
create.properties.password = {
|
|
186
195
|
type: 'string'
|
|
@@ -192,14 +201,9 @@ const buildEntitySchemas = async ({ entity, config, ctx })=>{
|
|
|
192
201
|
])
|
|
193
202
|
];
|
|
194
203
|
}
|
|
195
|
-
const update = cloneSchema(
|
|
204
|
+
const update = cloneSchema(write);
|
|
196
205
|
delete update.required;
|
|
197
206
|
if (update.properties) delete update.properties.id;
|
|
198
|
-
flattenRelationships({
|
|
199
|
-
schema: update,
|
|
200
|
-
fields: entity.fields,
|
|
201
|
-
idType
|
|
202
|
-
});
|
|
203
207
|
if (isAuth && update.properties) update.properties.password = {
|
|
204
208
|
type: 'string'
|
|
205
209
|
};
|
package/dist/spec/filters.js
CHANGED
|
@@ -3,7 +3,9 @@ const SYSTEM_COLLECTIONS = new Set([
|
|
|
3
3
|
'payload-locked-documents',
|
|
4
4
|
'payload-preferences',
|
|
5
5
|
'payload-migrations',
|
|
6
|
-
'payload-folders'
|
|
6
|
+
'payload-folders',
|
|
7
|
+
'payload-kv',
|
|
8
|
+
'payload-query-presets'
|
|
7
9
|
]);
|
|
8
10
|
const HTTP_METHODS = [
|
|
9
11
|
'get',
|
|
@@ -20,8 +22,15 @@ const matchesEntity = (matcher, { slug, kind })=>{
|
|
|
20
22
|
const anyMatch = (matchers, entity)=>matchers.some((m)=>matchesEntity(m, entity));
|
|
21
23
|
const isHiddenCollection = (collection)=>{
|
|
22
24
|
if (true === collection.hidden) return true;
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
+
const hidden = collection.admin?.hidden;
|
|
26
|
+
if ('function' == typeof hidden) try {
|
|
27
|
+
return true === hidden({
|
|
28
|
+
user: null
|
|
29
|
+
});
|
|
30
|
+
} catch {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
return true === hidden;
|
|
25
34
|
};
|
|
26
35
|
const passesIncludeExclude = (entity, filters)=>{
|
|
27
36
|
if (filters.include.length > 0 && !anyMatch(filters.include, entity)) return false;
|
package/dist/spec/params.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Field } from 'payload';
|
|
2
2
|
import type { ParameterObject, SchemaObject } from '@scalar/openapi-types/3.2';
|
|
3
|
-
import type { BuildContext } from '../types.js';
|
|
3
|
+
import type { BuildContext, Entity } from '../types.js';
|
|
4
4
|
export declare const buildSelectSchema: ({ fields, ctx }: {
|
|
5
5
|
fields: Field[];
|
|
6
6
|
ctx: BuildContext;
|
|
@@ -38,6 +38,14 @@ export declare const commonReadParams: ({ base, ctx, refs, }: {
|
|
|
38
38
|
ctx: BuildContext;
|
|
39
39
|
refs: ReadParamRefs;
|
|
40
40
|
}) => ParameterObject[];
|
|
41
|
+
export type WriteOperation = 'create' | 'update' | 'updateByID' | 'delete' | 'duplicate' | 'globalUpdate';
|
|
42
|
+
export declare const writeParams: ({ base, entity, ctx, refs, operation, }: {
|
|
43
|
+
base: string;
|
|
44
|
+
entity: Entity;
|
|
45
|
+
ctx: BuildContext;
|
|
46
|
+
refs: ReadParamRefs;
|
|
47
|
+
operation: WriteOperation;
|
|
48
|
+
}) => ParameterObject[];
|
|
41
49
|
export declare const whereParam: (base: string) => ParameterObject;
|
|
42
50
|
export declare const buildListParams: ({ base, fields, ctx, refs, }: {
|
|
43
51
|
base: string;
|
package/dist/spec/params.js
CHANGED
|
@@ -300,6 +300,98 @@ const commonReadParams = ({ base, ctx, refs })=>{
|
|
|
300
300
|
if (refs.joins) params.push(objectParam('joins', refTo(joinsSchemaName(base))));
|
|
301
301
|
return params;
|
|
302
302
|
};
|
|
303
|
+
const SHARED = [
|
|
304
|
+
'depth',
|
|
305
|
+
'locale',
|
|
306
|
+
'fallback-locale',
|
|
307
|
+
'select',
|
|
308
|
+
'populate'
|
|
309
|
+
];
|
|
310
|
+
const ALL_LOCALES = [
|
|
311
|
+
'publishAllLocales',
|
|
312
|
+
'unpublishAllLocales'
|
|
313
|
+
];
|
|
314
|
+
const WRITE_PARAMS = {
|
|
315
|
+
create: new Set([
|
|
316
|
+
...SHARED,
|
|
317
|
+
'draft',
|
|
318
|
+
'autosave',
|
|
319
|
+
'publishAllLocales'
|
|
320
|
+
]),
|
|
321
|
+
update: new Set([
|
|
322
|
+
...SHARED,
|
|
323
|
+
'draft',
|
|
324
|
+
'trash',
|
|
325
|
+
'overrideLock',
|
|
326
|
+
...ALL_LOCALES
|
|
327
|
+
]),
|
|
328
|
+
updateByID: new Set([
|
|
329
|
+
...SHARED,
|
|
330
|
+
'draft',
|
|
331
|
+
'trash',
|
|
332
|
+
'autosave',
|
|
333
|
+
'overrideLock',
|
|
334
|
+
...ALL_LOCALES
|
|
335
|
+
]),
|
|
336
|
+
delete: new Set([
|
|
337
|
+
...SHARED,
|
|
338
|
+
'trash',
|
|
339
|
+
'overrideLock'
|
|
340
|
+
]),
|
|
341
|
+
duplicate: new Set([
|
|
342
|
+
...SHARED,
|
|
343
|
+
'draft',
|
|
344
|
+
'selectedLocales[]'
|
|
345
|
+
]),
|
|
346
|
+
globalUpdate: new Set([
|
|
347
|
+
...SHARED,
|
|
348
|
+
'draft',
|
|
349
|
+
'autosave',
|
|
350
|
+
...ALL_LOCALES
|
|
351
|
+
])
|
|
352
|
+
};
|
|
353
|
+
const entityWriteParams = (entity, ctx)=>{
|
|
354
|
+
const t = makeT(ctx.i18n);
|
|
355
|
+
const flag = (name, key)=>({
|
|
356
|
+
name,
|
|
357
|
+
in: 'query',
|
|
358
|
+
description: t(key),
|
|
359
|
+
schema: {
|
|
360
|
+
type: 'boolean'
|
|
361
|
+
}
|
|
362
|
+
});
|
|
363
|
+
const drafts = entity.versions ? entity.versions.drafts : false;
|
|
364
|
+
const params = [];
|
|
365
|
+
if (drafts && drafts.autosave) params.push(flag('autosave', 'paramAutosave'));
|
|
366
|
+
if (drafts && drafts.localizeStatus) {
|
|
367
|
+
params.push(flag('publishAllLocales', 'paramPublishAllLocales'));
|
|
368
|
+
params.push(flag('unpublishAllLocales', 'paramUnpublishAllLocales'));
|
|
369
|
+
}
|
|
370
|
+
if (false !== entity.lockDocuments) params.push(flag('overrideLock', 'paramOverrideLock'));
|
|
371
|
+
if (ctx.locales.length > 0) params.push({
|
|
372
|
+
name: 'selectedLocales[]',
|
|
373
|
+
in: 'query',
|
|
374
|
+
description: t('paramSelectedLocales'),
|
|
375
|
+
style: 'form',
|
|
376
|
+
explode: true,
|
|
377
|
+
schema: {
|
|
378
|
+
type: 'array',
|
|
379
|
+
items: {
|
|
380
|
+
type: 'string',
|
|
381
|
+
enum: ctx.locales
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
return params;
|
|
386
|
+
};
|
|
387
|
+
const writeParams = ({ base, entity, ctx, refs, operation })=>[
|
|
388
|
+
...commonReadParams({
|
|
389
|
+
base,
|
|
390
|
+
ctx,
|
|
391
|
+
refs
|
|
392
|
+
}),
|
|
393
|
+
...entityWriteParams(entity, ctx)
|
|
394
|
+
].filter((p)=>WRITE_PARAMS[operation].has(p.name));
|
|
303
395
|
const whereParam = (base)=>objectParam('where', refTo(querySchemaName(base)));
|
|
304
396
|
const buildListParams = ({ base, fields, ctx, refs })=>{
|
|
305
397
|
const params = [
|
|
@@ -341,4 +433,4 @@ const buildListParams = ({ base, fields, ctx, refs })=>{
|
|
|
341
433
|
if (collectionHasFilters(fields)) params.push(whereParam(base));
|
|
342
434
|
return params;
|
|
343
435
|
};
|
|
344
|
-
export { buildJoinsSchema, buildListParams, buildParamSchemas, buildPopulateSchema, buildQueryOperationsSchema, buildSelectSchema, collectionHasFilters, commonReadParams, whereParam };
|
|
436
|
+
export { buildJoinsSchema, buildListParams, buildParamSchemas, buildPopulateSchema, buildQueryOperationsSchema, buildSelectSchema, collectionHasFilters, commonReadParams, whereParam, writeParams };
|
package/dist/spec/paths/auth.js
CHANGED
|
@@ -2,40 +2,63 @@ import { makeT } from "../../translations/index.js";
|
|
|
2
2
|
import { ERRORS, errorResponses, jsonBody, jsonResponse, messageResponse } from "../components.js";
|
|
3
3
|
import { refTo, schemaName } from "../names.js";
|
|
4
4
|
import { authTagName } from "../tags.js";
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
const identifierBody = (auth, extra = {})=>{
|
|
6
|
+
const email = {
|
|
7
|
+
type: 'string',
|
|
8
|
+
format: 'email'
|
|
9
|
+
};
|
|
10
|
+
const username = {
|
|
11
|
+
type: 'string'
|
|
12
|
+
};
|
|
13
|
+
const extraRequired = Object.keys(extra);
|
|
14
|
+
const loginWithUsername = auth?.loginWithUsername;
|
|
15
|
+
const base = {
|
|
16
|
+
type: 'object',
|
|
17
|
+
additionalProperties: false
|
|
18
|
+
};
|
|
19
|
+
if (!loginWithUsername) return {
|
|
20
|
+
...base,
|
|
9
21
|
properties: {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
22
|
+
email,
|
|
23
|
+
...extra
|
|
13
24
|
},
|
|
14
25
|
required: [
|
|
15
|
-
'
|
|
26
|
+
'email',
|
|
27
|
+
...extraRequired
|
|
16
28
|
]
|
|
17
29
|
};
|
|
18
|
-
if (loginWithUsername) return {
|
|
30
|
+
if ('object' == typeof loginWithUsername && loginWithUsername.allowEmailLogin) return {
|
|
31
|
+
...base,
|
|
19
32
|
properties: {
|
|
20
|
-
email
|
|
21
|
-
|
|
22
|
-
|
|
33
|
+
email,
|
|
34
|
+
username,
|
|
35
|
+
...extra
|
|
36
|
+
},
|
|
37
|
+
...extraRequired.length > 0 ? {
|
|
38
|
+
required: extraRequired
|
|
39
|
+
} : {},
|
|
40
|
+
anyOf: [
|
|
41
|
+
{
|
|
42
|
+
required: [
|
|
43
|
+
'email'
|
|
44
|
+
]
|
|
23
45
|
},
|
|
24
|
-
|
|
25
|
-
|
|
46
|
+
{
|
|
47
|
+
required: [
|
|
48
|
+
'username'
|
|
49
|
+
]
|
|
26
50
|
}
|
|
27
|
-
|
|
28
|
-
required: []
|
|
51
|
+
]
|
|
29
52
|
};
|
|
30
53
|
return {
|
|
54
|
+
...base,
|
|
31
55
|
properties: {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
format: 'email'
|
|
35
|
-
}
|
|
56
|
+
username,
|
|
57
|
+
...extra
|
|
36
58
|
},
|
|
37
59
|
required: [
|
|
38
|
-
'
|
|
60
|
+
'username',
|
|
61
|
+
...extraRequired
|
|
39
62
|
]
|
|
40
63
|
};
|
|
41
64
|
};
|
|
@@ -48,7 +71,6 @@ const buildAuthPaths = ({ collection, ctx, includeAdmin, nestedTags })=>{
|
|
|
48
71
|
const tag = [
|
|
49
72
|
nestedTags ? authTagName(name) : name
|
|
50
73
|
];
|
|
51
|
-
const ident = identifierProps(auth);
|
|
52
74
|
const userRef = {
|
|
53
75
|
$ref: refTo(name)
|
|
54
76
|
};
|
|
@@ -64,20 +86,11 @@ const buildAuthPaths = ({ collection, ctx, includeAdmin, nestedTags })=>{
|
|
|
64
86
|
const paths = {
|
|
65
87
|
[`${base}/login`]: {
|
|
66
88
|
post: op(`login${name}`, ERRORS.login, {
|
|
67
|
-
requestBody: jsonBody({
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
password: {
|
|
73
|
-
type: 'string'
|
|
74
|
-
}
|
|
75
|
-
},
|
|
76
|
-
required: [
|
|
77
|
-
...ident.required,
|
|
78
|
-
'password'
|
|
79
|
-
]
|
|
80
|
-
}),
|
|
89
|
+
requestBody: jsonBody(identifierBody(auth, {
|
|
90
|
+
password: {
|
|
91
|
+
type: 'string'
|
|
92
|
+
}
|
|
93
|
+
})),
|
|
81
94
|
responses: {
|
|
82
95
|
200: jsonResponse(t('authLogin'), {
|
|
83
96
|
type: 'object',
|
|
@@ -146,19 +159,7 @@ const buildAuthPaths = ({ collection, ctx, includeAdmin, nestedTags })=>{
|
|
|
146
159
|
},
|
|
147
160
|
[`${base}/forgot-password`]: {
|
|
148
161
|
post: op(`forgotPassword${name}`, ERRORS.authAction, {
|
|
149
|
-
requestBody: jsonBody(
|
|
150
|
-
type: 'object',
|
|
151
|
-
additionalProperties: false,
|
|
152
|
-
properties: {
|
|
153
|
-
email: {
|
|
154
|
-
type: 'string',
|
|
155
|
-
format: 'email'
|
|
156
|
-
}
|
|
157
|
-
},
|
|
158
|
-
required: [
|
|
159
|
-
'email'
|
|
160
|
-
]
|
|
161
|
-
}),
|
|
162
|
+
requestBody: jsonBody(identifierBody(auth)),
|
|
162
163
|
responses: messageResponse(t('authForgotPassword'))
|
|
163
164
|
})
|
|
164
165
|
},
|
|
@@ -247,21 +248,9 @@ const buildAuthPaths = ({ collection, ctx, includeAdmin, nestedTags })=>{
|
|
|
247
248
|
})
|
|
248
249
|
};
|
|
249
250
|
}
|
|
250
|
-
|
|
251
|
+
paths[`${base}/unlock`] = {
|
|
251
252
|
post: op(`unlock${name}`, ERRORS.authAction, {
|
|
252
|
-
requestBody: jsonBody(
|
|
253
|
-
type: 'object',
|
|
254
|
-
additionalProperties: false,
|
|
255
|
-
properties: {
|
|
256
|
-
email: {
|
|
257
|
-
type: 'string',
|
|
258
|
-
format: 'email'
|
|
259
|
-
}
|
|
260
|
-
},
|
|
261
|
-
required: [
|
|
262
|
-
'email'
|
|
263
|
-
]
|
|
264
|
-
}),
|
|
253
|
+
requestBody: jsonBody(identifierBody(auth)),
|
|
265
254
|
responses: messageResponse(t('authUnlock'))
|
|
266
255
|
})
|
|
267
256
|
};
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { SanitizedCollectionConfig } from 'payload';
|
|
2
2
|
import type { PathsObject } from '@scalar/openapi-types/3.2';
|
|
3
3
|
import type { BuildContext } from '../../types.js';
|
|
4
|
-
|
|
4
|
+
import type { EntitySecurity } from '../security.js';
|
|
5
|
+
export declare const buildCollectionPaths: ({ collection, ctx, security, }: {
|
|
5
6
|
collection: SanitizedCollectionConfig;
|
|
6
7
|
ctx: BuildContext;
|
|
8
|
+
security?: EntitySecurity;
|
|
7
9
|
}) => PathsObject;
|