@seshuk/payload-plugin-openapi 0.2.1 → 1.0.0-beta.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 +67 -25
- package/dist/_tooling/telemetry.js +168 -0
- package/dist/_tooling/telemetry.js.map +1 -0
- package/dist/cli/generateSpec.d.ts +2 -0
- package/dist/cli/generateSpec.js +40 -0
- package/dist/cli/generateSpec.js.map +1 -0
- package/dist/index.d.ts +8 -9
- package/dist/index.js +76 -65
- package/dist/index.js.map +1 -0
- package/dist/{endpoints → server/endpoints}/interactiveAuth.d.ts +2 -2
- package/dist/server/endpoints/interactiveAuth.js +25 -0
- package/dist/server/endpoints/interactiveAuth.js.map +1 -0
- package/dist/server/endpoints/spec.d.ts +5 -0
- package/dist/server/endpoints/spec.js +39 -0
- package/dist/server/endpoints/spec.js.map +1 -0
- package/dist/server/options/resolveOptions.d.ts +4 -0
- package/dist/server/options/resolveOptions.js +65 -0
- package/dist/server/options/resolveOptions.js.map +1 -0
- package/dist/server/spec/build.d.ts +14 -0
- package/dist/server/spec/build.js +40 -0
- package/dist/server/spec/build.js.map +1 -0
- package/dist/server/spec/buildDocument.d.ts +16 -0
- package/dist/server/spec/buildDocument.js +287 -0
- package/dist/server/spec/buildDocument.js.map +1 -0
- package/dist/server/spec/components.d.ts +61 -0
- package/dist/server/spec/components.js +265 -0
- package/dist/server/spec/components.js.map +1 -0
- package/dist/{spec → server/spec}/downconvert.d.ts +2 -1
- package/dist/server/spec/downconvert.js +69 -0
- package/dist/server/spec/downconvert.js.map +1 -0
- package/dist/server/spec/entitySchemas.d.ts +16 -0
- package/dist/server/spec/entitySchemas.js +207 -0
- package/dist/server/spec/entitySchemas.js.map +1 -0
- package/dist/{spec → server/spec}/fields.d.ts +2 -1
- package/dist/server/spec/fields.js +47 -0
- package/dist/server/spec/fields.js.map +1 -0
- package/dist/server/spec/filters.d.ts +12 -0
- package/dist/server/spec/filters.js +91 -0
- package/dist/server/spec/filters.js.map +1 -0
- package/dist/server/spec/hierarchy.d.ts +11 -0
- package/dist/server/spec/hierarchy.js +38 -0
- package/dist/server/spec/hierarchy.js.map +1 -0
- package/dist/{spec → server/spec}/names.d.ts +2 -2
- package/dist/server/spec/names.js +43 -0
- package/dist/server/spec/names.js.map +1 -0
- package/dist/server/spec/params.d.ts +57 -0
- package/dist/server/spec/params.js +394 -0
- package/dist/server/spec/params.js.map +1 -0
- package/dist/server/spec/paths/auth.d.ts +10 -0
- package/dist/server/spec/paths/auth.js +190 -0
- package/dist/server/spec/paths/auth.js.map +1 -0
- package/dist/server/spec/paths/collections.d.ts +11 -0
- package/dist/server/spec/paths/collections.js +314 -0
- package/dist/server/spec/paths/collections.js.map +1 -0
- package/dist/server/spec/paths/custom.d.ts +10 -0
- package/dist/server/spec/paths/custom.js +42 -0
- package/dist/server/spec/paths/custom.js.map +1 -0
- package/dist/server/spec/paths/globals.d.ts +11 -0
- package/dist/server/spec/paths/globals.js +87 -0
- package/dist/server/spec/paths/globals.js.map +1 -0
- package/dist/server/spec/paths/jobs.d.ts +9 -0
- package/dist/server/spec/paths/jobs.js +98 -0
- package/dist/server/spec/paths/jobs.js.map +1 -0
- package/dist/server/spec/paths/system.d.ts +8 -0
- package/dist/server/spec/paths/system.js +137 -0
- package/dist/server/spec/paths/system.js.map +1 -0
- package/dist/server/spec/paths/versions.d.ts +22 -0
- package/dist/server/spec/paths/versions.js +185 -0
- package/dist/server/spec/paths/versions.js.map +1 -0
- package/dist/server/spec/security.d.ts +33 -0
- package/dist/server/spec/security.js +97 -0
- package/dist/server/spec/security.js.map +1 -0
- package/dist/server/spec/tags.d.ts +34 -0
- package/dist/server/spec/tags.js +83 -0
- package/dist/server/spec/tags.js.map +1 -0
- package/dist/server/telemetry.d.ts +31 -0
- package/dist/server/telemetry.js +33 -0
- package/dist/server/telemetry.js.map +1 -0
- package/dist/server/ui/createUiPlugin.d.ts +16 -0
- package/dist/server/ui/createUiPlugin.js +33 -0
- package/dist/server/ui/createUiPlugin.js.map +1 -0
- package/dist/{ui → server/ui}/html.d.ts +5 -3
- package/dist/server/ui/html.js +11 -0
- package/dist/server/ui/html.js.map +1 -0
- package/dist/server/ui/scalar.d.ts +4 -0
- package/dist/server/ui/scalar.js +17 -0
- package/dist/server/ui/scalar.js.map +1 -0
- package/dist/server/ui/swagger.d.ts +4 -0
- package/dist/server/ui/swagger.js +18 -0
- package/dist/server/ui/swagger.js.map +1 -0
- package/dist/shared/constants.d.ts +4 -0
- package/dist/shared/constants.js +6 -0
- package/dist/shared/constants.js.map +1 -0
- package/dist/shared/translations/index.d.ts +5 -0
- package/dist/{translations → shared/translations}/index.js +49 -47
- package/dist/shared/translations/index.js.map +1 -0
- package/dist/shared/translations/locales/ar.d.ts +3 -0
- package/dist/shared/translations/locales/ar.js +99 -0
- package/dist/shared/translations/locales/ar.js.map +1 -0
- package/dist/shared/translations/locales/az.d.ts +3 -0
- package/dist/shared/translations/locales/az.js +99 -0
- package/dist/shared/translations/locales/az.js.map +1 -0
- package/dist/shared/translations/locales/bg.d.ts +3 -0
- package/dist/shared/translations/locales/bg.js +99 -0
- package/dist/shared/translations/locales/bg.js.map +1 -0
- package/dist/shared/translations/locales/bnBd.d.ts +3 -0
- package/dist/shared/translations/locales/bnBd.js +99 -0
- package/dist/shared/translations/locales/bnBd.js.map +1 -0
- package/dist/shared/translations/locales/bnIn.d.ts +3 -0
- package/dist/shared/translations/locales/bnIn.js +99 -0
- package/dist/shared/translations/locales/bnIn.js.map +1 -0
- package/dist/shared/translations/locales/ca.d.ts +3 -0
- package/dist/shared/translations/locales/ca.js +99 -0
- package/dist/shared/translations/locales/ca.js.map +1 -0
- package/dist/shared/translations/locales/cs.d.ts +3 -0
- package/dist/shared/translations/locales/cs.js +99 -0
- package/dist/shared/translations/locales/cs.js.map +1 -0
- package/dist/shared/translations/locales/da.d.ts +3 -0
- package/dist/shared/translations/locales/da.js +99 -0
- package/dist/shared/translations/locales/da.js.map +1 -0
- package/dist/shared/translations/locales/de.d.ts +3 -0
- package/dist/shared/translations/locales/de.js +99 -0
- package/dist/shared/translations/locales/de.js.map +1 -0
- package/dist/shared/translations/locales/en.d.ts +3 -0
- package/dist/shared/translations/locales/en.js +99 -0
- package/dist/shared/translations/locales/en.js.map +1 -0
- package/dist/shared/translations/locales/es.d.ts +3 -0
- package/dist/shared/translations/locales/es.js +99 -0
- package/dist/shared/translations/locales/es.js.map +1 -0
- package/dist/shared/translations/locales/et.d.ts +3 -0
- package/dist/shared/translations/locales/et.js +99 -0
- package/dist/shared/translations/locales/et.js.map +1 -0
- package/dist/shared/translations/locales/fa.d.ts +3 -0
- package/dist/shared/translations/locales/fa.js +99 -0
- package/dist/shared/translations/locales/fa.js.map +1 -0
- package/dist/shared/translations/locales/fr.d.ts +3 -0
- package/dist/shared/translations/locales/fr.js +99 -0
- package/dist/shared/translations/locales/fr.js.map +1 -0
- package/dist/shared/translations/locales/he.d.ts +3 -0
- package/dist/shared/translations/locales/he.js +99 -0
- package/dist/shared/translations/locales/he.js.map +1 -0
- package/dist/shared/translations/locales/hr.d.ts +3 -0
- package/dist/shared/translations/locales/hr.js +99 -0
- package/dist/shared/translations/locales/hr.js.map +1 -0
- package/dist/shared/translations/locales/hu.d.ts +3 -0
- package/dist/shared/translations/locales/hu.js +99 -0
- package/dist/shared/translations/locales/hu.js.map +1 -0
- package/dist/shared/translations/locales/hy.d.ts +3 -0
- package/dist/shared/translations/locales/hy.js +99 -0
- package/dist/shared/translations/locales/hy.js.map +1 -0
- package/dist/shared/translations/locales/id.d.ts +3 -0
- package/dist/shared/translations/locales/id.js +99 -0
- package/dist/shared/translations/locales/id.js.map +1 -0
- package/dist/shared/translations/locales/is.d.ts +3 -0
- package/dist/shared/translations/locales/is.js +99 -0
- package/dist/shared/translations/locales/is.js.map +1 -0
- package/dist/shared/translations/locales/it.d.ts +3 -0
- package/dist/shared/translations/locales/it.js +99 -0
- package/dist/shared/translations/locales/it.js.map +1 -0
- package/dist/shared/translations/locales/ja.d.ts +3 -0
- package/dist/shared/translations/locales/ja.js +99 -0
- package/dist/shared/translations/locales/ja.js.map +1 -0
- package/dist/shared/translations/locales/ko.d.ts +3 -0
- package/dist/shared/translations/locales/ko.js +99 -0
- package/dist/shared/translations/locales/ko.js.map +1 -0
- package/dist/shared/translations/locales/lt.d.ts +3 -0
- package/dist/shared/translations/locales/lt.js +99 -0
- package/dist/shared/translations/locales/lt.js.map +1 -0
- package/dist/shared/translations/locales/lv.d.ts +3 -0
- package/dist/shared/translations/locales/lv.js +99 -0
- package/dist/shared/translations/locales/lv.js.map +1 -0
- package/dist/shared/translations/locales/my.d.ts +3 -0
- package/dist/shared/translations/locales/my.js +99 -0
- package/dist/shared/translations/locales/my.js.map +1 -0
- package/dist/shared/translations/locales/nb.d.ts +3 -0
- package/dist/shared/translations/locales/nb.js +99 -0
- package/dist/shared/translations/locales/nb.js.map +1 -0
- package/dist/shared/translations/locales/nl.d.ts +3 -0
- package/dist/shared/translations/locales/nl.js +99 -0
- package/dist/shared/translations/locales/nl.js.map +1 -0
- package/dist/shared/translations/locales/pl.d.ts +3 -0
- package/dist/shared/translations/locales/pl.js +99 -0
- package/dist/shared/translations/locales/pl.js.map +1 -0
- package/dist/shared/translations/locales/pt.d.ts +3 -0
- package/dist/shared/translations/locales/pt.js +99 -0
- package/dist/shared/translations/locales/pt.js.map +1 -0
- package/dist/shared/translations/locales/ro.d.ts +3 -0
- package/dist/shared/translations/locales/ro.js +99 -0
- package/dist/shared/translations/locales/ro.js.map +1 -0
- package/dist/shared/translations/locales/rs.d.ts +3 -0
- package/dist/shared/translations/locales/rs.js +99 -0
- package/dist/shared/translations/locales/rs.js.map +1 -0
- package/dist/shared/translations/locales/rsLatin.d.ts +3 -0
- package/dist/shared/translations/locales/rsLatin.js +99 -0
- package/dist/shared/translations/locales/rsLatin.js.map +1 -0
- package/dist/shared/translations/locales/ru.d.ts +3 -0
- package/dist/shared/translations/locales/ru.js +99 -0
- package/dist/shared/translations/locales/ru.js.map +1 -0
- package/dist/shared/translations/locales/sk.d.ts +3 -0
- package/dist/shared/translations/locales/sk.js +99 -0
- package/dist/shared/translations/locales/sk.js.map +1 -0
- package/dist/shared/translations/locales/sl.d.ts +3 -0
- package/dist/shared/translations/locales/sl.js +99 -0
- package/dist/shared/translations/locales/sl.js.map +1 -0
- package/dist/shared/translations/locales/sv.d.ts +3 -0
- package/dist/shared/translations/locales/sv.js +99 -0
- package/dist/shared/translations/locales/sv.js.map +1 -0
- package/dist/shared/translations/locales/ta.d.ts +3 -0
- package/dist/shared/translations/locales/ta.js +99 -0
- package/dist/shared/translations/locales/ta.js.map +1 -0
- package/dist/shared/translations/locales/th.d.ts +3 -0
- package/dist/shared/translations/locales/th.js +99 -0
- package/dist/shared/translations/locales/th.js.map +1 -0
- package/dist/shared/translations/locales/tr.d.ts +3 -0
- package/dist/shared/translations/locales/tr.js +99 -0
- package/dist/shared/translations/locales/tr.js.map +1 -0
- package/dist/shared/translations/locales/uk.d.ts +3 -0
- package/dist/shared/translations/locales/uk.js +99 -0
- package/dist/shared/translations/locales/uk.js.map +1 -0
- package/dist/shared/translations/locales/vi.d.ts +3 -0
- package/dist/shared/translations/locales/vi.js +99 -0
- package/dist/shared/translations/locales/vi.js.map +1 -0
- package/dist/shared/translations/locales/zh.d.ts +3 -0
- package/dist/shared/translations/locales/zh.js +99 -0
- package/dist/shared/translations/locales/zh.js.map +1 -0
- package/dist/shared/translations/locales/zhTw.d.ts +3 -0
- package/dist/shared/translations/locales/zhTw.js +99 -0
- package/dist/shared/translations/locales/zhTw.js.map +1 -0
- package/dist/shared/translations/types.d.ts +106 -0
- package/dist/shared/translations/types.js +1 -0
- package/dist/shared/types/index.d.ts +397 -0
- package/dist/shared/types/index.js +1 -0
- package/dist/{utils.d.ts → shared/utils.d.ts} +1 -0
- package/dist/shared/utils.js +13 -0
- package/dist/shared/utils.js.map +1 -0
- package/package.json +67 -56
- package/dist/bin/generateSpec.d.ts +0 -25
- package/dist/bin/generateSpec.js +0 -61
- package/dist/constants.d.ts +0 -1
- package/dist/constants.js +0 -2
- package/dist/endpoints/interactiveAuth.js +0 -27
- package/dist/endpoints/spec.d.ts +0 -5
- package/dist/endpoints/spec.js +0 -39
- package/dist/options.d.ts +0 -2
- package/dist/options.js +0 -45
- package/dist/spec/build.d.ts +0 -14
- package/dist/spec/build.js +0 -36
- package/dist/spec/buildDocument.d.ts +0 -15
- package/dist/spec/buildDocument.js +0 -268
- package/dist/spec/components.d.ts +0 -44
- package/dist/spec/components.js +0 -265
- package/dist/spec/downconvert.js +0 -74
- package/dist/spec/entitySchemas.d.ts +0 -15
- package/dist/spec/entitySchemas.js +0 -250
- package/dist/spec/fields.js +0 -44
- package/dist/spec/filters.d.ts +0 -11
- package/dist/spec/filters.js +0 -83
- package/dist/spec/names.js +0 -37
- package/dist/spec/params.d.ts +0 -55
- package/dist/spec/params.js +0 -436
- package/dist/spec/paths/auth.d.ts +0 -9
- package/dist/spec/paths/auth.js +0 -274
- package/dist/spec/paths/collections.d.ts +0 -9
- package/dist/spec/paths/collections.js +0 -278
- package/dist/spec/paths/custom.d.ts +0 -9
- package/dist/spec/paths/custom.js +0 -41
- package/dist/spec/paths/globals.d.ts +0 -9
- package/dist/spec/paths/globals.js +0 -78
- package/dist/spec/paths/jobs.d.ts +0 -7
- package/dist/spec/paths/jobs.js +0 -130
- package/dist/spec/paths/versions.d.ts +0 -19
- package/dist/spec/paths/versions.js +0 -252
- package/dist/spec/security.d.ts +0 -19
- package/dist/spec/security.js +0 -96
- package/dist/spec/tags.d.ts +0 -27
- package/dist/spec/tags.js +0 -79
- package/dist/translations/index.d.ts +0 -6
- package/dist/translations/locales/ar.d.ts +0 -2
- package/dist/translations/locales/ar.js +0 -81
- package/dist/translations/locales/az.d.ts +0 -2
- package/dist/translations/locales/az.js +0 -81
- package/dist/translations/locales/bg.d.ts +0 -2
- package/dist/translations/locales/bg.js +0 -81
- package/dist/translations/locales/bnBd.d.ts +0 -2
- package/dist/translations/locales/bnBd.js +0 -81
- package/dist/translations/locales/bnIn.d.ts +0 -2
- package/dist/translations/locales/bnIn.js +0 -81
- package/dist/translations/locales/ca.d.ts +0 -2
- package/dist/translations/locales/ca.js +0 -81
- package/dist/translations/locales/cs.d.ts +0 -2
- package/dist/translations/locales/cs.js +0 -81
- package/dist/translations/locales/da.d.ts +0 -2
- package/dist/translations/locales/da.js +0 -81
- package/dist/translations/locales/de.d.ts +0 -2
- package/dist/translations/locales/de.js +0 -81
- package/dist/translations/locales/en.d.ts +0 -2
- package/dist/translations/locales/en.js +0 -81
- package/dist/translations/locales/es.d.ts +0 -2
- package/dist/translations/locales/es.js +0 -81
- package/dist/translations/locales/et.d.ts +0 -2
- package/dist/translations/locales/et.js +0 -81
- package/dist/translations/locales/fa.d.ts +0 -2
- package/dist/translations/locales/fa.js +0 -81
- package/dist/translations/locales/fr.d.ts +0 -2
- package/dist/translations/locales/fr.js +0 -81
- package/dist/translations/locales/he.d.ts +0 -2
- package/dist/translations/locales/he.js +0 -81
- package/dist/translations/locales/hr.d.ts +0 -2
- package/dist/translations/locales/hr.js +0 -81
- package/dist/translations/locales/hu.d.ts +0 -2
- package/dist/translations/locales/hu.js +0 -81
- package/dist/translations/locales/hy.d.ts +0 -2
- package/dist/translations/locales/hy.js +0 -81
- package/dist/translations/locales/id.d.ts +0 -2
- package/dist/translations/locales/id.js +0 -81
- package/dist/translations/locales/is.d.ts +0 -2
- package/dist/translations/locales/is.js +0 -81
- package/dist/translations/locales/it.d.ts +0 -2
- package/dist/translations/locales/it.js +0 -81
- package/dist/translations/locales/ja.d.ts +0 -2
- package/dist/translations/locales/ja.js +0 -81
- package/dist/translations/locales/ko.d.ts +0 -2
- package/dist/translations/locales/ko.js +0 -81
- package/dist/translations/locales/lt.d.ts +0 -2
- package/dist/translations/locales/lt.js +0 -81
- package/dist/translations/locales/lv.d.ts +0 -2
- package/dist/translations/locales/lv.js +0 -81
- package/dist/translations/locales/my.d.ts +0 -2
- package/dist/translations/locales/my.js +0 -81
- package/dist/translations/locales/nb.d.ts +0 -2
- package/dist/translations/locales/nb.js +0 -81
- package/dist/translations/locales/nl.d.ts +0 -2
- package/dist/translations/locales/nl.js +0 -81
- package/dist/translations/locales/pl.d.ts +0 -2
- package/dist/translations/locales/pl.js +0 -81
- package/dist/translations/locales/pt.d.ts +0 -2
- package/dist/translations/locales/pt.js +0 -81
- package/dist/translations/locales/ro.d.ts +0 -2
- package/dist/translations/locales/ro.js +0 -81
- package/dist/translations/locales/rs.d.ts +0 -2
- package/dist/translations/locales/rs.js +0 -81
- package/dist/translations/locales/rsLatin.d.ts +0 -2
- package/dist/translations/locales/rsLatin.js +0 -81
- package/dist/translations/locales/ru.d.ts +0 -2
- package/dist/translations/locales/ru.js +0 -81
- package/dist/translations/locales/sk.d.ts +0 -2
- package/dist/translations/locales/sk.js +0 -81
- package/dist/translations/locales/sl.d.ts +0 -2
- package/dist/translations/locales/sl.js +0 -81
- package/dist/translations/locales/sv.d.ts +0 -2
- package/dist/translations/locales/sv.js +0 -81
- package/dist/translations/locales/ta.d.ts +0 -2
- package/dist/translations/locales/ta.js +0 -81
- package/dist/translations/locales/th.d.ts +0 -2
- package/dist/translations/locales/th.js +0 -81
- package/dist/translations/locales/tr.d.ts +0 -2
- package/dist/translations/locales/tr.js +0 -81
- package/dist/translations/locales/uk.d.ts +0 -2
- package/dist/translations/locales/uk.js +0 -81
- package/dist/translations/locales/vi.d.ts +0 -2
- package/dist/translations/locales/vi.js +0 -81
- package/dist/translations/locales/zh.d.ts +0 -2
- package/dist/translations/locales/zh.js +0 -81
- package/dist/translations/locales/zhTw.d.ts +0 -2
- package/dist/translations/locales/zhTw.js +0 -81
- package/dist/translations/types.d.ts +0 -87
- package/dist/translations/types.js +0 -1
- package/dist/types.d.ts +0 -192
- package/dist/types.js +0 -1
- package/dist/ui/createUiPlugin.d.ts +0 -14
- package/dist/ui/createUiPlugin.js +0 -28
- package/dist/ui/html.js +0 -8
- package/dist/ui/scalar.d.ts +0 -1
- package/dist/ui/scalar.js +0 -12
- package/dist/ui/swagger.d.ts +0 -1
- package/dist/ui/swagger.js +0 -12
- package/dist/utils.js +0 -13
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
3
|
<picture>
|
|
4
|
-
<img src="docs/logo.svg" alt="OpenAPI Plugin for Payload
|
|
4
|
+
<img src="docs/logo.svg" alt="OpenAPI Plugin for Payload" height="80" />
|
|
5
5
|
</picture>
|
|
6
6
|
|
|
7
|
-
<h1>OpenAPI Plugin for Payload
|
|
7
|
+
<h1>OpenAPI Plugin for Payload</h1>
|
|
8
8
|
|
|
9
9
|
<p>Generate an OpenAPI 3.0/3.1/3.2 specification from your Payload config and serve it with Scalar or Swagger UI.</p>
|
|
10
10
|
|
|
@@ -14,13 +14,13 @@
|
|
|
14
14
|
<a href="https://github.com/maximseshuk/payload-plugin-openapi/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/maximseshuk/payload-plugin-openapi/ci.yml?style=flat-square&logo=github" alt="CI" /></a>
|
|
15
15
|
<a href="https://payload-plugin-openapi.seshuk.im/"><img src="https://img.shields.io/badge/docs-payload--plugin--openapi.seshuk.im-blue?style=flat-square&logo=readthedocs&logoColor=white" alt="Documentation" /></a>
|
|
16
16
|
<a href="https://github.com/maximseshuk/payload-plugin-openapi/blob/main/LICENSE"><img src="https://img.shields.io/github/license/maximseshuk/payload-plugin-openapi?style=flat-square" alt="license" /></a>
|
|
17
|
-
<a href="https://ko-fi.com/
|
|
17
|
+
<a href="https://ko-fi.com/seshuk"><img src="https://img.shields.io/badge/Ko--fi-Buy_me_a_coffee-ff5f5f?style=flat-square&logo=ko-fi&logoColor=white" alt="Ko-fi" /></a>
|
|
18
18
|
|
|
19
19
|
</div>
|
|
20
20
|
|
|
21
21
|
## Features
|
|
22
22
|
|
|
23
|
-
- **Full spec from your config** — collections, globals, auth, versions, and jobs are documented with zero annotation.
|
|
23
|
+
- **Full spec from your config** — collections, globals, auth, versions, uploads, and jobs are documented with zero annotation. See the [endpoint list](https://payload-plugin-openapi.seshuk.im/v1/reference/endpoints).
|
|
24
24
|
- **Interactive docs included** — mount Scalar or Swagger UI, or both on different paths.
|
|
25
25
|
- **Native metadata** — document custom endpoints and refine field schemas through Payload's own `custom.openapi` key. No wrapper, no separate registry.
|
|
26
26
|
- **Precise filtering** — choose exactly which entities and operations end up in the spec.
|
|
@@ -31,16 +31,16 @@
|
|
|
31
31
|
|
|
32
32
|
## Quick start
|
|
33
33
|
|
|
34
|
-
Requires **Payload
|
|
34
|
+
Requires **Payload 4.0.0-canary.38**, **Next.js 16.4 or later** and **Node.js 24.15 or later**. On Payload 3, use `@seshuk/payload-plugin-openapi@0`.
|
|
35
35
|
|
|
36
36
|
### Install
|
|
37
37
|
|
|
38
38
|
```bash
|
|
39
|
-
npm install @seshuk/payload-plugin-openapi
|
|
40
|
-
yarn add @seshuk/payload-plugin-openapi
|
|
41
|
-
pnpm add @seshuk/payload-plugin-openapi
|
|
39
|
+
npm install @seshuk/payload-plugin-openapi@beta
|
|
42
40
|
```
|
|
43
41
|
|
|
42
|
+
v1 is in beta under the `beta` npm tag, and Payload 4 is published under `canary`.
|
|
43
|
+
|
|
44
44
|
### Configure
|
|
45
45
|
|
|
46
46
|
Add the plugin to your Payload config, plus a docs UI renderer:
|
|
@@ -52,7 +52,7 @@ import { openapi, scalar } from '@seshuk/payload-plugin-openapi'
|
|
|
52
52
|
export default buildConfig({
|
|
53
53
|
plugins: [
|
|
54
54
|
openapi({
|
|
55
|
-
|
|
55
|
+
info: {
|
|
56
56
|
title: 'My API',
|
|
57
57
|
version: '1.0.0',
|
|
58
58
|
},
|
|
@@ -67,38 +67,80 @@ Two endpoints are now live, both relative to your API route (`/api` by default):
|
|
|
67
67
|
- `GET /api/openapi.json` — the generated OpenAPI document
|
|
68
68
|
- `GET /api/docs` — the interactive API reference
|
|
69
69
|
|
|
70
|
-
`
|
|
70
|
+
`info.title` and `info.version` are required; the plugin throws at boot without them. Prefer Swagger UI? Swap `scalar()` for `swaggerUi()`, or mount both on different paths.
|
|
71
71
|
|
|
72
72
|
The document is built lazily from the fully sanitized config, so collections, fields, and endpoints added by other plugins are picked up regardless of plugin order.
|
|
73
73
|
|
|
74
|
-
Add `filters` to control what is exposed, `interactiveAuth` for a login dialog in the docs UI, `extensions` for anything the generator doesn't produce on its own — see the [configuration reference](https://payload-plugin-openapi.seshuk.im/configuration/overview).
|
|
74
|
+
Add `filters` to control what is exposed, `interactiveAuth` for a login dialog in the docs UI, `extensions` for anything the generator doesn't produce on its own — see the [configuration reference](https://payload-plugin-openapi.seshuk.im/v1/configuration/overview).
|
|
75
|
+
|
|
76
|
+
## Upgrading from 0.x
|
|
77
|
+
|
|
78
|
+
v1 renames a few options. The plugin throws at boot when it finds an old name.
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
// 0.x
|
|
82
|
+
openapi({
|
|
83
|
+
metadata: { title, version },
|
|
84
|
+
specEndpoint: '/spec.json',
|
|
85
|
+
interactiveAuth: { endpoint: '/login' },
|
|
86
|
+
securityWhen: ({ slug }) => (slug === 'feed' ? true : undefined),
|
|
87
|
+
filters: { excludeWhen: ({ path }) => path.includes('/internal/') },
|
|
88
|
+
})
|
|
89
|
+
scalar({ specEndpoint: '/api/spec.json' })
|
|
90
|
+
|
|
91
|
+
// v1
|
|
92
|
+
openapi({
|
|
93
|
+
info: { title, version },
|
|
94
|
+
path: '/spec.json',
|
|
95
|
+
interactiveAuth: { path: '/login' },
|
|
96
|
+
security: ({ slug }) => (slug === 'feed' ? 'public' : undefined),
|
|
97
|
+
filters: { excludeOperations: [({ path }) => path.includes('/internal/')] },
|
|
98
|
+
})
|
|
99
|
+
scalar() // follows the openapi() path; use specURL for another URL
|
|
100
|
+
|
|
101
|
+
// 0.x
|
|
102
|
+
custom: { openapi: { security: { read: true, create: false } } }
|
|
103
|
+
|
|
104
|
+
// v1
|
|
105
|
+
custom: { openapi: { security: { read: 'public', create: 'secured' } } }
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
The spec no longer reads `servers` from the `Host` header. It uses `serverURL`, the new `servers` option, or hosts you list in `trustedHosts`. An extension `transform` that throws now fails the request. The spec and docs page are open by default. Add `access` to `openapi()` and `scalar()` to make them private. See [Upgrading from 0.x](https://payload-plugin-openapi.seshuk.im/v1/upgrade-guide).
|
|
75
109
|
|
|
76
110
|
## Documentation
|
|
77
111
|
|
|
78
112
|
Full docs are at **<https://payload-plugin-openapi.seshuk.im/>**:
|
|
79
113
|
|
|
80
|
-
- [Quick start](https://payload-plugin-openapi.seshuk.im/quick-start)
|
|
81
|
-
- [Configuration reference](https://payload-plugin-openapi.seshuk.im/configuration/overview)
|
|
82
|
-
- [Filters](https://payload-plugin-openapi.seshuk.im/configuration/filters)
|
|
83
|
-
- [Security marking](https://payload-plugin-openapi.seshuk.im/configuration/security-marking)
|
|
84
|
-
- [Docs UI — Scalar & Swagger](https://payload-plugin-openapi.seshuk.im/configuration/docs-ui)
|
|
85
|
-
- [Documenting custom endpoints](https://payload-plugin-openapi.seshuk.im/guides/custom-endpoints)
|
|
86
|
-
- [Field metadata](https://payload-plugin-openapi.seshuk.im/guides/field-metadata)
|
|
87
|
-
- [CLI — `openapi:generate`](https://payload-plugin-openapi.seshuk.im/cli/generate)
|
|
88
|
-
- [Examples](https://payload-plugin-openapi.seshuk.im/guides/examples)
|
|
114
|
+
- [Quick start](https://payload-plugin-openapi.seshuk.im/v1/quick-start)
|
|
115
|
+
- [Configuration reference](https://payload-plugin-openapi.seshuk.im/v1/configuration/overview)
|
|
116
|
+
- [Filters](https://payload-plugin-openapi.seshuk.im/v1/configuration/filters)
|
|
117
|
+
- [Security marking](https://payload-plugin-openapi.seshuk.im/v1/configuration/security-marking)
|
|
118
|
+
- [Docs UI — Scalar & Swagger](https://payload-plugin-openapi.seshuk.im/v1/configuration/docs-ui)
|
|
119
|
+
- [Documenting custom endpoints](https://payload-plugin-openapi.seshuk.im/v1/guides/custom-endpoints)
|
|
120
|
+
- [Field metadata](https://payload-plugin-openapi.seshuk.im/v1/guides/field-metadata)
|
|
121
|
+
- [CLI — `openapi:generate`](https://payload-plugin-openapi.seshuk.im/v1/cli/generate)
|
|
122
|
+
- [Examples](https://payload-plugin-openapi.seshuk.im/v1/guides/examples)
|
|
89
123
|
|
|
90
124
|
## For plugin authors
|
|
91
125
|
|
|
92
|
-
If you maintain a Payload plugin, attach a `custom.openapi` Operation Object to the endpoints you add and they show up in the generated spec — no dependency on this package, and nothing for your users to wire up. The same key works on fields. If this plugin isn't installed, the metadata is inert. See [For plugin authors](https://payload-plugin-openapi.seshuk.im/guides/plugin-authors).
|
|
126
|
+
If you maintain a Payload plugin, attach a `custom.openapi` Operation Object to the endpoints you add and they show up in the generated spec — no dependency on this package, and nothing for your users to wire up. The same key works on fields. If this plugin isn't installed, the metadata is inert. See [For plugin authors](https://payload-plugin-openapi.seshuk.im/v1/guides/plugin-authors).
|
|
127
|
+
|
|
128
|
+
## Telemetry
|
|
129
|
+
|
|
130
|
+
The plugin sends an anonymous, opt-out usage report once per day: plugin, Payload, and Node versions plus which features are enabled. It never sends secrets, IPs, keys, URLs, paths, hostnames, collection names, or anything from your spec. A one-time notice prints on first run.
|
|
131
|
+
|
|
132
|
+
Opt out with `telemetry: false`, `DO_NOT_TRACK=1`, or `OPENAPI_TELEMETRY_DISABLED=1` (also disabled automatically in CI and when `payload.config.telemetry` is `false`). See [Telemetry](https://payload-plugin-openapi.seshuk.im/v1/configuration/telemetry) for the full list of what is and isn't collected.
|
|
93
133
|
|
|
94
134
|
## Related plugins
|
|
95
135
|
|
|
96
|
-
- **[@seshuk/payload-storage-bunny](https://github.com/maximseshuk/payload-storage-bunny)** — store files and stream video from Payload
|
|
97
|
-
- **[@seshuk/payload-plugin-media-preview](https://github.com/maximseshuk/payload-plugin-media-preview)** — preview images, video, audio
|
|
136
|
+
- **[@seshuk/payload-storage-bunny](https://github.com/maximseshuk/payload-storage-bunny)** — store files and stream video from Payload on Bunny.net's global CDN.
|
|
137
|
+
- **[@seshuk/payload-plugin-media-preview](https://github.com/maximseshuk/payload-plugin-media-preview)** — preview images, video, audio and documents in the Payload admin panel.
|
|
138
|
+
- **[@seshuk/payload-plugin-janitor](https://github.com/maximseshuk/payload-plugin-janitor)** — find orphaned files and unused documents, then delete only what you approve.
|
|
139
|
+
- **[@seshuk/payload-plugin-sitemap](https://github.com/maximseshuk/payload-plugin-sitemap)** — sitemaps for Payload, stored with any storage adapter.
|
|
98
140
|
|
|
99
141
|
## Support
|
|
100
142
|
|
|
101
|
-
Bug reports, feature requests, and questions go to [GitHub Issues](https://github.com/maximseshuk/payload-plugin-openapi/issues). For Payload itself, see the [Payload
|
|
143
|
+
Bug reports, feature requests, and questions go to [GitHub Issues](https://github.com/maximseshuk/payload-plugin-openapi/issues). For Payload itself, see the [Payload docs](https://payloadcms.com/docs) and [Discord](https://discord.gg/payloadcms).
|
|
102
144
|
|
|
103
145
|
## License
|
|
104
146
|
|
|
@@ -106,6 +148,6 @@ MIT — see [LICENSE](LICENSE).
|
|
|
106
148
|
|
|
107
149
|
## Credits
|
|
108
150
|
|
|
109
|
-
Built by [Maxim Seshuk](https://github.com/maximseshuk) for the Payload
|
|
151
|
+
Built by [Maxim Seshuk](https://github.com/maximseshuk) for the Payload community.
|
|
110
152
|
|
|
111
153
|
If this plugin saves you time, you can [buy me a coffee](https://ko-fi.com/seshuk) ☕
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
import { execSync } from "node:child_process";
|
|
4
|
+
import { createHash } from "node:crypto";
|
|
5
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
6
|
+
import { tmpdir } from "node:os";
|
|
7
|
+
import { dirname, join } from "node:path";
|
|
8
|
+
const TELEMETRY_ENDPOINT = "https://telemetry.seshuk.im/v1/collect";
|
|
9
|
+
const isTruthyEnv = (value) => value !== void 0 && value !== "" && value !== "0" && value.toLowerCase() !== "false";
|
|
10
|
+
const isTelemetryDisabled = ({ disableEnv, env, option, payloadTelemetry }) => {
|
|
11
|
+
if (payloadTelemetry === false || option === false) return true;
|
|
12
|
+
if (isTruthyEnv(env[disableEnv]) || isTruthyEnv(env.DO_NOT_TRACK) || isTruthyEnv(env.CI)) return true;
|
|
13
|
+
return env.NODE_ENV === "test";
|
|
14
|
+
};
|
|
15
|
+
const hashProjectId = (secret, rawSource) => createHash("sha256").update(secret + rawSource).digest("hex");
|
|
16
|
+
const resolveRawSource = (candidates) => {
|
|
17
|
+
if (candidates.git) return {
|
|
18
|
+
source: "git",
|
|
19
|
+
value: candidates.git
|
|
20
|
+
};
|
|
21
|
+
if (candidates.packageJSON) return {
|
|
22
|
+
source: "packageJSON",
|
|
23
|
+
value: candidates.packageJSON
|
|
24
|
+
};
|
|
25
|
+
if (candidates.serverURL) return {
|
|
26
|
+
source: "serverURL",
|
|
27
|
+
value: candidates.serverURL
|
|
28
|
+
};
|
|
29
|
+
return {
|
|
30
|
+
source: "cwd",
|
|
31
|
+
value: candidates.cwd
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
const readGitRemote = () => {
|
|
35
|
+
try {
|
|
36
|
+
return execSync("git config --local --get remote.origin.url", {
|
|
37
|
+
stdio: [
|
|
38
|
+
"ignore",
|
|
39
|
+
"pipe",
|
|
40
|
+
"ignore"
|
|
41
|
+
],
|
|
42
|
+
timeout: 1e3
|
|
43
|
+
}).toString().trim() || void 0;
|
|
44
|
+
} catch {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
const readJson = (file) => {
|
|
49
|
+
try {
|
|
50
|
+
return JSON.parse(readFileSync(file, "utf8"));
|
|
51
|
+
} catch {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
const readAppPackageName = (cwd) => {
|
|
56
|
+
const name = readJson(join(cwd, "package.json"))?.name;
|
|
57
|
+
return typeof name === "string" && name ? name : void 0;
|
|
58
|
+
};
|
|
59
|
+
const deriveProjectId = ({ cwd = process.cwd(), git, packageJSON, secret, serverURL }) => {
|
|
60
|
+
const raw = resolveRawSource({
|
|
61
|
+
cwd,
|
|
62
|
+
git: git ?? readGitRemote(),
|
|
63
|
+
packageJSON: packageJSON ?? readAppPackageName(cwd),
|
|
64
|
+
serverURL
|
|
65
|
+
});
|
|
66
|
+
return {
|
|
67
|
+
projectId: hashProjectId(secret, raw.value),
|
|
68
|
+
projectIdSource: raw.source
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
const utcDay = (now = /* @__PURE__ */ new Date()) => now.toISOString().slice(0, 10);
|
|
72
|
+
const stateFile = (product, projectId) => join(tmpdir(), `${product}-telemetry-${projectId}.json`);
|
|
73
|
+
const readState = (product, projectId) => {
|
|
74
|
+
try {
|
|
75
|
+
return JSON.parse(readFileSync(stateFile(product, projectId), "utf8"));
|
|
76
|
+
} catch {
|
|
77
|
+
return {};
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
const writeState = (product, projectId, state) => {
|
|
81
|
+
try {
|
|
82
|
+
writeFileSync(stateFile(product, projectId), JSON.stringify(state));
|
|
83
|
+
} catch {}
|
|
84
|
+
};
|
|
85
|
+
const findPackageVersion = (name, from) => {
|
|
86
|
+
let dir = from;
|
|
87
|
+
while (true) {
|
|
88
|
+
const pkg = readJson(join(dir, "package.json"));
|
|
89
|
+
if (pkg?.name === name && typeof pkg.version === "string" && pkg.version) return pkg.version;
|
|
90
|
+
const parent = dirname(dir);
|
|
91
|
+
if (parent === dir) return;
|
|
92
|
+
dir = parent;
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
const readPackageVersion = (packageName, from = dirname(fileURLToPath(import.meta.url))) => findPackageVersion(packageName, from) ?? "0.0.0";
|
|
96
|
+
const readPayloadVersion = () => {
|
|
97
|
+
try {
|
|
98
|
+
return findPackageVersion("payload", dirname(createRequire(import.meta.url).resolve("payload"))) ?? "0.0.0";
|
|
99
|
+
} catch {
|
|
100
|
+
return "0.0.0";
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
const buildReport = ({ features, payloadVersion, product, productVersion, projectId, projectIdSource }) => ({
|
|
104
|
+
features,
|
|
105
|
+
os: process.platform.toLowerCase().slice(0, 16),
|
|
106
|
+
payloadVersion,
|
|
107
|
+
product,
|
|
108
|
+
productVersion,
|
|
109
|
+
projectId,
|
|
110
|
+
projectIdSource,
|
|
111
|
+
runtime: "node",
|
|
112
|
+
runtimeVersion: process.versions.node.split(".")[0],
|
|
113
|
+
schema: 1
|
|
114
|
+
});
|
|
115
|
+
const postReport = async (report, endpoint) => {
|
|
116
|
+
try {
|
|
117
|
+
await fetch(endpoint, {
|
|
118
|
+
body: JSON.stringify(report),
|
|
119
|
+
headers: { "content-type": "application/json" },
|
|
120
|
+
method: "POST",
|
|
121
|
+
signal: AbortSignal.timeout(2e3)
|
|
122
|
+
});
|
|
123
|
+
} catch {}
|
|
124
|
+
};
|
|
125
|
+
const reportTelemetry = async ({ disableEnv, docsUrl, features, option, packageName, payload, product }, deps = {}) => {
|
|
126
|
+
const env = deps.env ?? process.env;
|
|
127
|
+
const readStateImpl = deps.readState ?? ((projectId) => readState(product, projectId));
|
|
128
|
+
const writeStateImpl = deps.writeState ?? ((projectId, state) => writeState(product, projectId, state));
|
|
129
|
+
const send = deps.send ?? postReport;
|
|
130
|
+
try {
|
|
131
|
+
if (isTelemetryDisabled({
|
|
132
|
+
disableEnv,
|
|
133
|
+
env,
|
|
134
|
+
option,
|
|
135
|
+
payloadTelemetry: payload.config.telemetry
|
|
136
|
+
})) return;
|
|
137
|
+
const { projectId, projectIdSource } = deriveProjectId({
|
|
138
|
+
secret: payload.secret,
|
|
139
|
+
serverURL: payload.config.serverURL
|
|
140
|
+
});
|
|
141
|
+
const state = readStateImpl(projectId);
|
|
142
|
+
const today = utcDay(deps.now);
|
|
143
|
+
if (!state.noticeShown) payload.logger.info(`[${product}] Anonymous usage telemetry is on: plugin, Payload and Node versions and the features you use. It never sends secrets, IPs, keys or names. Opt out with telemetry: false, DO_NOT_TRACK=1 or ${disableEnv}=1. What is sent: ${docsUrl}`);
|
|
144
|
+
if (state.lastSentDay === today) {
|
|
145
|
+
if (!state.noticeShown) writeStateImpl(projectId, {
|
|
146
|
+
...state,
|
|
147
|
+
noticeShown: true
|
|
148
|
+
});
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const report = buildReport({
|
|
152
|
+
features,
|
|
153
|
+
payloadVersion: readPayloadVersion(),
|
|
154
|
+
product,
|
|
155
|
+
productVersion: readPackageVersion(packageName),
|
|
156
|
+
projectId,
|
|
157
|
+
projectIdSource
|
|
158
|
+
});
|
|
159
|
+
writeStateImpl(projectId, {
|
|
160
|
+
lastSentDay: today,
|
|
161
|
+
noticeShown: true
|
|
162
|
+
});
|
|
163
|
+
await send(report, typeof option === "object" && option.url ? option.url : TELEMETRY_ENDPOINT);
|
|
164
|
+
} catch {}
|
|
165
|
+
};
|
|
166
|
+
export { buildReport, deriveProjectId, hashProjectId, isTelemetryDisabled, postReport, readPackageVersion, readPayloadVersion, readState, reportTelemetry, resolveRawSource, utcDay, writeState };
|
|
167
|
+
|
|
168
|
+
//# sourceMappingURL=telemetry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.js","names":[],"sources":["node_modules/@seshuk/payload-plugin-tooling/dist/telemetry.js"],"sourcesContent":["import { createRequire } from \"node:module\";\nimport { execSync } from \"node:child_process\";\nimport { createHash } from \"node:crypto\";\nimport { readFileSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n//#region src/telemetry.ts\nconst TELEMETRY_ENDPOINT = \"https://telemetry.seshuk.im/v1/collect\";\nconst isTruthyEnv = (value) => value !== void 0 && value !== \"\" && value !== \"0\" && value.toLowerCase() !== \"false\";\nconst isTelemetryDisabled = ({ disableEnv, env, option, payloadTelemetry }) => {\n\tif (payloadTelemetry === false || option === false) return true;\n\tif (isTruthyEnv(env[disableEnv]) || isTruthyEnv(env.DO_NOT_TRACK) || isTruthyEnv(env.CI)) return true;\n\treturn env.NODE_ENV === \"test\";\n};\nconst hashProjectId = (secret, rawSource) => createHash(\"sha256\").update(secret + rawSource).digest(\"hex\");\nconst resolveRawSource = (candidates) => {\n\tif (candidates.git) return {\n\t\tsource: \"git\",\n\t\tvalue: candidates.git\n\t};\n\tif (candidates.packageJSON) return {\n\t\tsource: \"packageJSON\",\n\t\tvalue: candidates.packageJSON\n\t};\n\tif (candidates.serverURL) return {\n\t\tsource: \"serverURL\",\n\t\tvalue: candidates.serverURL\n\t};\n\treturn {\n\t\tsource: \"cwd\",\n\t\tvalue: candidates.cwd\n\t};\n};\nconst readGitRemote = () => {\n\ttry {\n\t\treturn execSync(\"git config --local --get remote.origin.url\", {\n\t\t\tstdio: [\n\t\t\t\t\"ignore\",\n\t\t\t\t\"pipe\",\n\t\t\t\t\"ignore\"\n\t\t\t],\n\t\t\ttimeout: 1e3\n\t\t}).toString().trim() || void 0;\n\t} catch {\n\t\treturn;\n\t}\n};\nconst readJson = (file) => {\n\ttry {\n\t\treturn JSON.parse(readFileSync(file, \"utf8\"));\n\t} catch {\n\t\treturn;\n\t}\n};\nconst readAppPackageName = (cwd) => {\n\tconst name = readJson(join(cwd, \"package.json\"))?.name;\n\treturn typeof name === \"string\" && name ? name : void 0;\n};\nconst deriveProjectId = ({ cwd = process.cwd(), git, packageJSON, secret, serverURL }) => {\n\tconst raw = resolveRawSource({\n\t\tcwd,\n\t\tgit: git ?? readGitRemote(),\n\t\tpackageJSON: packageJSON ?? readAppPackageName(cwd),\n\t\tserverURL\n\t});\n\treturn {\n\t\tprojectId: hashProjectId(secret, raw.value),\n\t\tprojectIdSource: raw.source\n\t};\n};\nconst utcDay = (now = /* @__PURE__ */ new Date()) => now.toISOString().slice(0, 10);\nconst stateFile = (product, projectId) => join(tmpdir(), `${product}-telemetry-${projectId}.json`);\nconst readState = (product, projectId) => {\n\ttry {\n\t\treturn JSON.parse(readFileSync(stateFile(product, projectId), \"utf8\"));\n\t} catch {\n\t\treturn {};\n\t}\n};\nconst writeState = (product, projectId, state) => {\n\ttry {\n\t\twriteFileSync(stateFile(product, projectId), JSON.stringify(state));\n\t} catch {}\n};\nconst findPackageVersion = (name, from) => {\n\tlet dir = from;\n\twhile (true) {\n\t\tconst pkg = readJson(join(dir, \"package.json\"));\n\t\tif (pkg?.name === name && typeof pkg.version === \"string\" && pkg.version) return pkg.version;\n\t\tconst parent = dirname(dir);\n\t\tif (parent === dir) return;\n\t\tdir = parent;\n\t}\n};\nconst readPackageVersion = (packageName, from = dirname(fileURLToPath(import.meta.url))) => findPackageVersion(packageName, from) ?? \"0.0.0\";\nconst readPayloadVersion = () => {\n\ttry {\n\t\treturn findPackageVersion(\"payload\", dirname(createRequire(import.meta.url).resolve(\"payload\"))) ?? \"0.0.0\";\n\t} catch {\n\t\treturn \"0.0.0\";\n\t}\n};\nconst buildReport = ({ features, payloadVersion, product, productVersion, projectId, projectIdSource }) => ({\n\tfeatures,\n\tos: process.platform.toLowerCase().slice(0, 16),\n\tpayloadVersion,\n\tproduct,\n\tproductVersion,\n\tprojectId,\n\tprojectIdSource,\n\truntime: \"node\",\n\truntimeVersion: process.versions.node.split(\".\")[0],\n\tschema: 1\n});\nconst postReport = async (report, endpoint) => {\n\ttry {\n\t\tawait fetch(endpoint, {\n\t\t\tbody: JSON.stringify(report),\n\t\t\theaders: { \"content-type\": \"application/json\" },\n\t\t\tmethod: \"POST\",\n\t\t\tsignal: AbortSignal.timeout(2e3)\n\t\t});\n\t} catch {}\n};\nconst reportTelemetry = async ({ disableEnv, docsUrl, features, option, packageName, payload, product }, deps = {}) => {\n\tconst env = deps.env ?? process.env;\n\tconst readStateImpl = deps.readState ?? ((projectId) => readState(product, projectId));\n\tconst writeStateImpl = deps.writeState ?? ((projectId, state) => writeState(product, projectId, state));\n\tconst send = deps.send ?? postReport;\n\ttry {\n\t\tif (isTelemetryDisabled({\n\t\t\tdisableEnv,\n\t\t\tenv,\n\t\t\toption,\n\t\t\tpayloadTelemetry: payload.config.telemetry\n\t\t})) return;\n\t\tconst { projectId, projectIdSource } = deriveProjectId({\n\t\t\tsecret: payload.secret,\n\t\t\tserverURL: payload.config.serverURL\n\t\t});\n\t\tconst state = readStateImpl(projectId);\n\t\tconst today = utcDay(deps.now);\n\t\tif (!state.noticeShown) payload.logger.info(`[${product}] Anonymous usage telemetry is on: plugin, Payload and Node versions and the features you use. It never sends secrets, IPs, keys or names. Opt out with telemetry: false, DO_NOT_TRACK=1 or ${disableEnv}=1. What is sent: ${docsUrl}`);\n\t\tif (state.lastSentDay === today) {\n\t\t\tif (!state.noticeShown) writeStateImpl(projectId, {\n\t\t\t\t...state,\n\t\t\t\tnoticeShown: true\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tconst report = buildReport({\n\t\t\tfeatures,\n\t\t\tpayloadVersion: readPayloadVersion(),\n\t\t\tproduct,\n\t\t\tproductVersion: readPackageVersion(packageName),\n\t\t\tprojectId,\n\t\t\tprojectIdSource\n\t\t});\n\t\twriteStateImpl(projectId, {\n\t\t\tlastSentDay: today,\n\t\t\tnoticeShown: true\n\t\t});\n\t\tawait send(report, typeof option === \"object\" && option.url ? option.url : TELEMETRY_ENDPOINT);\n\t} catch {}\n};\n//#endregion\nexport { buildReport, deriveProjectId, hashProjectId, isTelemetryDisabled, postReport, readPackageVersion, readPayloadVersion, readState, reportTelemetry, resolveRawSource, utcDay, writeState };\n"],"ignoreList":[0],"mappings":";;;;;;;AAQA,MAAM,qBAAqB;AAC3B,MAAM,eAAe,UAAU,UAAU,KAAK,KAAK,UAAU,MAAM,UAAU,OAAO,MAAM,YAAY,MAAM;AAC5G,MAAM,uBAAuB,EAAE,YAAY,KAAK,QAAQ,uBAAuB;CAC9E,IAAI,qBAAqB,SAAS,WAAW,OAAO,OAAO;CAC3D,IAAI,YAAY,IAAI,WAAW,KAAK,YAAY,IAAI,YAAY,KAAK,YAAY,IAAI,EAAE,GAAG,OAAO;CACjG,OAAO,IAAI,aAAa;AACzB;AACA,MAAM,iBAAiB,QAAQ,cAAc,WAAW,QAAQ,CAAC,CAAC,OAAO,SAAS,SAAS,CAAC,CAAC,OAAO,KAAK;AACzG,MAAM,oBAAoB,eAAe;CACxC,IAAI,WAAW,KAAK,OAAO;EAC1B,QAAQ;EACR,OAAO,WAAW;CACnB;CACA,IAAI,WAAW,aAAa,OAAO;EAClC,QAAQ;EACR,OAAO,WAAW;CACnB;CACA,IAAI,WAAW,WAAW,OAAO;EAChC,QAAQ;EACR,OAAO,WAAW;CACnB;CACA,OAAO;EACN,QAAQ;EACR,OAAO,WAAW;CACnB;AACD;AACA,MAAM,sBAAsB;CAC3B,IAAI;EACH,OAAO,SAAS,8CAA8C;GAC7D,OAAO;IACN;IACA;IACA;GACD;GACA,SAAS;EACV,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,KAAK,KAAK,KAAK;CAC9B,QAAQ;EACP;CACD;AACD;AACA,MAAM,YAAY,SAAS;CAC1B,IAAI;EACH,OAAO,KAAK,MAAM,aAAa,MAAM,MAAM,CAAC;CAC7C,QAAQ;EACP;CACD;AACD;AACA,MAAM,sBAAsB,QAAQ;CACnC,MAAM,OAAO,SAAS,KAAK,KAAK,cAAc,CAAC,CAAC,EAAE;CAClD,OAAO,OAAO,SAAS,YAAY,OAAO,OAAO,KAAK;AACvD;AACA,MAAM,mBAAmB,EAAE,MAAM,QAAQ,IAAI,GAAG,KAAK,aAAa,QAAQ,gBAAgB;CACzF,MAAM,MAAM,iBAAiB;EAC5B;EACA,KAAK,OAAO,cAAc;EAC1B,aAAa,eAAe,mBAAmB,GAAG;EAClD;CACD,CAAC;CACD,OAAO;EACN,WAAW,cAAc,QAAQ,IAAI,KAAK;EAC1C,iBAAiB,IAAI;CACtB;AACD;AACA,MAAM,UAAU,sBAAsB,IAAI,KAAK,MAAM,IAAI,YAAY,CAAC,CAAC,MAAM,GAAG,EAAE;AAClF,MAAM,aAAa,SAAS,cAAc,KAAK,OAAO,GAAG,GAAG,QAAQ,aAAa,UAAU,MAAM;AACjG,MAAM,aAAa,SAAS,cAAc;CACzC,IAAI;EACH,OAAO,KAAK,MAAM,aAAa,UAAU,SAAS,SAAS,GAAG,MAAM,CAAC;CACtE,QAAQ;EACP,OAAO,CAAC;CACT;AACD;AACA,MAAM,cAAc,SAAS,WAAW,UAAU;CACjD,IAAI;EACH,cAAc,UAAU,SAAS,SAAS,GAAG,KAAK,UAAU,KAAK,CAAC;CACnE,QAAQ,CAAC;AACV;AACA,MAAM,sBAAsB,MAAM,SAAS;CAC1C,IAAI,MAAM;CACV,OAAO,MAAM;EACZ,MAAM,MAAM,SAAS,KAAK,KAAK,cAAc,CAAC;EAC9C,IAAI,KAAK,SAAS,QAAQ,OAAO,IAAI,YAAY,YAAY,IAAI,SAAS,OAAO,IAAI;EACrF,MAAM,SAAS,QAAQ,GAAG;EAC1B,IAAI,WAAW,KAAK;EACpB,MAAM;CACP;AACD;AACA,MAAM,sBAAsB,aAAa,OAAO,QAAQ,cAAc,YAAY,GAAG,CAAC,MAAM,mBAAmB,aAAa,IAAI,KAAK;AACrI,MAAM,2BAA2B;CAChC,IAAI;EACH,OAAO,mBAAmB,WAAW,QAAQ,cAAc,YAAY,GAAG,CAAC,CAAC,QAAQ,SAAS,CAAC,CAAC,KAAK;CACrG,QAAQ;EACP,OAAO;CACR;AACD;AACA,MAAM,eAAe,EAAE,UAAU,gBAAgB,SAAS,gBAAgB,WAAW,uBAAuB;CAC3G;CACA,IAAI,QAAQ,SAAS,YAAY,CAAC,CAAC,MAAM,GAAG,EAAE;CAC9C;CACA;CACA;CACA;CACA;CACA,SAAS;CACT,gBAAgB,QAAQ,SAAS,KAAK,MAAM,GAAG,CAAC,CAAC;CACjD,QAAQ;AACT;AACA,MAAM,aAAa,OAAO,QAAQ,aAAa;CAC9C,IAAI;EACH,MAAM,MAAM,UAAU;GACrB,MAAM,KAAK,UAAU,MAAM;GAC3B,SAAS,EAAE,gBAAgB,mBAAmB;GAC9C,QAAQ;GACR,QAAQ,YAAY,QAAQ,GAAG;EAChC,CAAC;CACF,QAAQ,CAAC;AACV;AACA,MAAM,kBAAkB,OAAO,EAAE,YAAY,SAAS,UAAU,QAAQ,aAAa,SAAS,WAAW,OAAO,CAAC,MAAM;CACtH,MAAM,MAAM,KAAK,OAAO,QAAQ;CAChC,MAAM,gBAAgB,KAAK,eAAe,cAAc,UAAU,SAAS,SAAS;CACpF,MAAM,iBAAiB,KAAK,gBAAgB,WAAW,UAAU,WAAW,SAAS,WAAW,KAAK;CACrG,MAAM,OAAO,KAAK,QAAQ;CAC1B,IAAI;EACH,IAAI,oBAAoB;GACvB;GACA;GACA;GACA,kBAAkB,QAAQ,OAAO;EAClC,CAAC,GAAG;EACJ,MAAM,EAAE,WAAW,oBAAoB,gBAAgB;GACtD,QAAQ,QAAQ;GAChB,WAAW,QAAQ,OAAO;EAC3B,CAAC;EACD,MAAM,QAAQ,cAAc,SAAS;EACrC,MAAM,QAAQ,OAAO,KAAK,GAAG;EAC7B,IAAI,CAAC,MAAM,aAAa,QAAQ,OAAO,KAAK,IAAI,QAAQ,8LAA8L,WAAW,oBAAoB,SAAS;EAC9R,IAAI,MAAM,gBAAgB,OAAO;GAChC,IAAI,CAAC,MAAM,aAAa,eAAe,WAAW;IACjD,GAAG;IACH,aAAa;GACd,CAAC;GACD;EACD;EACA,MAAM,SAAS,YAAY;GAC1B;GACA,gBAAgB,mBAAmB;GACnC;GACA,gBAAgB,mBAAmB,WAAW;GAC9C;GACA;EACD,CAAC;EACD,eAAe,WAAW;GACzB,aAAa;GACb,aAAa;EACd,CAAC;EACD,MAAM,KAAK,QAAQ,OAAO,WAAW,YAAY,OAAO,MAAM,OAAO,MAAM,kBAAkB;CAC9F,QAAQ,CAAC;AACV"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { PLUGIN_NAME } from "../shared/constants.js";
|
|
2
|
+
import { buildOpenApiDocument } from "../server/spec/build.js";
|
|
3
|
+
import { strictObject, z } from "payload";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { writeFile } from "node:fs/promises";
|
|
6
|
+
import { defineCLICommand } from "payload/cli";
|
|
7
|
+
const optionalString = (description) => z.optional(z.string()).check(z.describe(description));
|
|
8
|
+
const generateSpecCommand = defineCLICommand({
|
|
9
|
+
description: "Write the OpenAPI document to a file.",
|
|
10
|
+
input: strictObject({
|
|
11
|
+
lang: optionalString("Locale for translated descriptions; `all` writes one file per supported language. Defaults to the i18n fallback."),
|
|
12
|
+
out: optionalString("Output file for a single-language run (default openapi.json)."),
|
|
13
|
+
server: optionalString("Base URL written to the document `servers`. Defaults to the `servers` option, then `serverURL`.")
|
|
14
|
+
}),
|
|
15
|
+
handler: async ({ args, getConfig, getPayload }) => {
|
|
16
|
+
const config = await getConfig();
|
|
17
|
+
const resolved = config.custom?.[PLUGIN_NAME];
|
|
18
|
+
if (!resolved) throw new Error(`${PLUGIN_NAME}: plugin is not registered in payload.config — no resolved options found on config.custom['${PLUGIN_NAME}'].`);
|
|
19
|
+
const payload = await getPayload();
|
|
20
|
+
const { lang, out, server } = args;
|
|
21
|
+
const servers = server ? [{ url: server }] : void 0;
|
|
22
|
+
const fallback = config.i18n?.fallbackLanguage ?? "en";
|
|
23
|
+
const supported = config.i18n?.supportedLanguages ? Object.keys(config.i18n.supportedLanguages) : [fallback];
|
|
24
|
+
const langs = lang === "all" ? supported : [lang ?? fallback];
|
|
25
|
+
for (const language of langs) {
|
|
26
|
+
const doc = await buildOpenApiDocument({
|
|
27
|
+
payload,
|
|
28
|
+
options: resolved,
|
|
29
|
+
language,
|
|
30
|
+
servers
|
|
31
|
+
});
|
|
32
|
+
const file = langs.length > 1 ? `openapi.${language}.json` : out ?? "openapi.json";
|
|
33
|
+
await writeFile(path.resolve(file), `${JSON.stringify(doc, null, 2)}\n`);
|
|
34
|
+
payload.logger.info(`Wrote ${file}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
export { generateSpecCommand };
|
|
39
|
+
|
|
40
|
+
//# sourceMappingURL=generateSpec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateSpec.js","names":[],"sources":["../../src/cli/generateSpec.ts"],"sourcesContent":["import { writeFile } from 'node:fs/promises'\nimport path from 'node:path'\n\nimport { strictObject, z } from 'payload'\nimport { defineCLICommand } from 'payload/cli'\n\nimport { buildOpenApiDocument } from '@/server/spec/build.js'\nimport { PLUGIN_NAME } from '@/shared/constants.js'\nimport type { ResolvedOptions } from '@/shared/types/index.js'\n\nconst optionalString = (description: string) => z.optional(z.string()).check(z.describe(description))\n\nexport const generateSpecCommand = defineCLICommand({\n description: 'Write the OpenAPI document to a file.',\n input: strictObject({\n lang: optionalString(\n 'Locale for translated descriptions; `all` writes one file per supported language. Defaults to the i18n fallback.',\n ),\n out: optionalString('Output file for a single-language run (default openapi.json).'),\n server: optionalString(\n 'Base URL written to the document `servers`. Defaults to the `servers` option, then `serverURL`.',\n ),\n }),\n handler: async ({ args, getConfig, getPayload }) => {\n const config = await getConfig()\n const resolved = config.custom?.[PLUGIN_NAME] as ResolvedOptions | undefined\n if (!resolved) {\n throw new Error(\n `${PLUGIN_NAME}: plugin is not registered in payload.config — no resolved options found on config.custom['${PLUGIN_NAME}'].`,\n )\n }\n\n const payload = await getPayload()\n const { lang, out, server } = args\n const servers = server ? [{ url: server }] : undefined\n\n const fallback = config.i18n?.fallbackLanguage ?? 'en'\n const supported = config.i18n?.supportedLanguages ? Object.keys(config.i18n.supportedLanguages) : [fallback]\n const langs = lang === 'all' ? supported : [lang ?? fallback]\n\n for (const language of langs) {\n const doc = await buildOpenApiDocument({ payload, options: resolved, language, servers })\n const file = langs.length > 1 ? `openapi.${language}.json` : (out ?? 'openapi.json')\n await writeFile(path.resolve(file), `${JSON.stringify(doc, null, 2)}\\n`)\n payload.logger.info(`Wrote ${file}`)\n }\n },\n})\n"],"mappings":";;;;;;AAUA,MAAM,kBAAkB,gBAAwB,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,SAAS,WAAW,CAAC;AAEpG,MAAa,sBAAsB,iBAAiB;CAClD,aAAa;CACb,OAAO,aAAa;EAClB,MAAM,eACJ,kHACF;EACA,KAAK,eAAe,+DAA+D;EACnF,QAAQ,eACN,iGACF;CACF,CAAC;CACD,SAAS,OAAO,EAAE,MAAM,WAAW,iBAAiB;EAClD,MAAM,SAAS,MAAM,UAAU;EAC/B,MAAM,WAAW,OAAO,SAAS;EACjC,IAAI,CAAC,UACH,MAAM,IAAI,MACR,GAAG,YAAY,6FAA6F,YAAY,IAC1H;EAGF,MAAM,UAAU,MAAM,WAAW;EACjC,MAAM,EAAE,MAAM,KAAK,WAAW;EAC9B,MAAM,UAAU,SAAS,CAAC,EAAE,KAAK,OAAO,CAAC,IAAI,KAAA;EAE7C,MAAM,WAAW,OAAO,MAAM,oBAAoB;EAClD,MAAM,YAAY,OAAO,MAAM,qBAAqB,OAAO,KAAK,OAAO,KAAK,kBAAkB,IAAI,CAAC,QAAQ;EAC3G,MAAM,QAAQ,SAAS,QAAQ,YAAY,CAAC,QAAQ,QAAQ;EAE5D,KAAK,MAAM,YAAY,OAAO;GAC5B,MAAM,MAAM,MAAM,qBAAqB;IAAE;IAAS,SAAS;IAAU;IAAU;GAAQ,CAAC;GACxF,MAAM,OAAO,MAAM,SAAS,IAAI,WAAW,SAAS,SAAU,OAAO;GACrE,MAAM,UAAU,KAAK,QAAQ,IAAI,GAAG,GAAG,KAAK,UAAU,KAAK,MAAM,CAAC,EAAE,GAAG;GACvE,QAAQ,OAAO,KAAK,SAAS,MAAM;EACrC;CACF;AACF,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export
|
|
7
|
-
export { scalar
|
|
8
|
-
|
|
9
|
-
export type { BuildContext, EntityOperation, EntitySecurityOverride, FilterOptions, OpenApiExtension, OpenApiMetadata, OpenApiPluginOptions, OpenApiVersion, OperationContext, UiPluginOptions, } from './types.js';
|
|
1
|
+
import { AccessOption, BuildContext, EntityOpenApiMeta, EntityOperation, EntitySecurityOverride, ExtensionContext, FieldOpenApiMeta, FilterOptions, LocalizedText, OpenApiExtension, OpenApiInfo, OpenApiPluginOptions, OpenApiVersion, OperationContext, OperationFilter, OperationKind, OperationRule, SecurityMarking, SecurityOption, ServersOption, UiPluginOptions } from "./shared/types/index.js";
|
|
2
|
+
import { BuildOpenApiInput, buildOpenApiDocument } from "./server/spec/build.js";
|
|
3
|
+
import { toOpenApi30, toOpenApi31 } from "./server/spec/downconvert.js";
|
|
4
|
+
import { scalar } from "./server/ui/scalar.js";
|
|
5
|
+
import { swaggerUi } from "./server/ui/swagger.js";
|
|
6
|
+
export declare const openapi: (options: OpenApiPluginOptions) => import("payload").Plugin;
|
|
7
|
+
export { type AccessOption, type BuildContext, type BuildOpenApiInput, type EntityOpenApiMeta, type EntityOperation, type EntitySecurityOverride, type ExtensionContext, type FieldOpenApiMeta, type FilterOptions, type LocalizedText, type OpenApiExtension, type OpenApiInfo, type OpenApiPluginOptions, type OpenApiVersion, type OperationContext, type OperationFilter, type OperationKind, type OperationRule, type SecurityMarking, type SecurityOption, type ServersOption, type UiPluginOptions, buildOpenApiDocument, scalar, swaggerUi, toOpenApi30, toOpenApi31 };
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -1,67 +1,78 @@
|
|
|
1
|
+
import { interactiveAuthHandler } from "./server/endpoints/interactiveAuth.js";
|
|
2
|
+
import { PLUGIN_NAME } from "./shared/constants.js";
|
|
3
|
+
import { translations } from "./shared/translations/index.js";
|
|
4
|
+
import { readSecurityOverride } from "./server/spec/security.js";
|
|
5
|
+
import { toOpenApi30, toOpenApi31 } from "./server/spec/downconvert.js";
|
|
6
|
+
import { buildOpenApiDocument } from "./server/spec/build.js";
|
|
7
|
+
import { specHandler } from "./server/endpoints/spec.js";
|
|
8
|
+
import { resolveOptions } from "./server/options/resolveOptions.js";
|
|
9
|
+
import { buildFeatures, reportOpenApiTelemetry } from "./server/telemetry.js";
|
|
10
|
+
import { scalar } from "./server/ui/scalar.js";
|
|
11
|
+
import { swaggerUi } from "./server/ui/swagger.js";
|
|
1
12
|
import { fileURLToPath } from "node:url";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const resolveBinScriptPath = ()=>{
|
|
9
|
-
const selfUrl = new URL(import.meta.url);
|
|
10
|
-
const ext = selfUrl.pathname.endsWith('.ts') ? '.ts' : '.js';
|
|
11
|
-
return fileURLToPath(new URL(`./bin/generateSpec${ext}`, selfUrl));
|
|
13
|
+
import { definePlugin } from "payload";
|
|
14
|
+
const CLI_COMMAND = "openapi:generate";
|
|
15
|
+
const resolveCommandPath = () => {
|
|
16
|
+
const selfUrl = new URL(import.meta.url);
|
|
17
|
+
const ext = selfUrl.pathname.endsWith(".ts") ? ".ts" : ".js";
|
|
18
|
+
return `${fileURLToPath(new URL(`./cli/generateSpec${ext}`, selfUrl))}#generateSpecCommand`;
|
|
12
19
|
};
|
|
13
|
-
const openapi = (
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
20
|
+
const openapi = definePlugin({
|
|
21
|
+
slug: PLUGIN_NAME,
|
|
22
|
+
plugin: ({ config, options, plugins }) => {
|
|
23
|
+
const resolved = resolveOptions(options);
|
|
24
|
+
for (const entity of [...config.collections ?? [], ...config.globals ?? []]) readSecurityOverride(entity);
|
|
25
|
+
if (options.enabled === false) return config;
|
|
26
|
+
const authCollection = resolved.interactiveAuth.collection ?? (config.collections ?? []).find((c) => Boolean(c.auth))?.slug ?? "users";
|
|
27
|
+
const features = buildFeatures({
|
|
28
|
+
plugins,
|
|
29
|
+
resolved
|
|
30
|
+
});
|
|
31
|
+
config.i18n = config.i18n ?? {};
|
|
32
|
+
config.i18n.translations = config.i18n.translations ?? {};
|
|
33
|
+
const supportedKeys = config.i18n.supportedLanguages ? Object.keys(config.i18n.supportedLanguages) : ["en"];
|
|
34
|
+
for (const lang of supportedKeys) {
|
|
35
|
+
const pluginEntry = translations[lang];
|
|
36
|
+
if (!pluginEntry) continue;
|
|
37
|
+
const typedLang = lang;
|
|
38
|
+
config.i18n.translations[typedLang] = {
|
|
39
|
+
...config.i18n.translations[typedLang],
|
|
40
|
+
[PLUGIN_NAME]: pluginEntry[PLUGIN_NAME]
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
...config,
|
|
45
|
+
custom: {
|
|
46
|
+
...config.custom,
|
|
47
|
+
[PLUGIN_NAME]: resolved
|
|
48
|
+
},
|
|
49
|
+
cli: config.cli === false ? config.cli : {
|
|
50
|
+
...config.cli,
|
|
51
|
+
commands: {
|
|
52
|
+
[CLI_COMMAND]: resolveCommandPath(),
|
|
53
|
+
...config.cli?.commands
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
endpoints: [...config.endpoints ?? [], ...resolved.serve ? [{
|
|
57
|
+
path: resolved.path,
|
|
58
|
+
method: "get",
|
|
59
|
+
handler: specHandler(resolved)
|
|
60
|
+
}, ...resolved.interactiveAuth.enabled ? [{
|
|
61
|
+
path: resolved.interactiveAuth.path,
|
|
62
|
+
method: "post",
|
|
63
|
+
handler: interactiveAuthHandler(authCollection)
|
|
64
|
+
}] : []] : []],
|
|
65
|
+
onInit: async (payload) => {
|
|
66
|
+
await config.onInit?.(payload);
|
|
67
|
+
reportOpenApiTelemetry({
|
|
68
|
+
features,
|
|
69
|
+
options,
|
|
70
|
+
payload
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
export { buildOpenApiDocument, openapi, scalar, swaggerUi, toOpenApi30, toOpenApi31 };
|
|
77
|
+
|
|
78
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import { fileURLToPath } from 'node:url'\n\nimport { definePlugin } from 'payload'\n\nimport { interactiveAuthHandler } from '@/server/endpoints/interactiveAuth.js'\nimport { specHandler } from '@/server/endpoints/spec.js'\nimport { resolveOptions } from '@/server/options/resolveOptions.js'\nimport { readSecurityOverride } from '@/server/spec/security.js'\nimport { buildFeatures, reportOpenApiTelemetry } from '@/server/telemetry.js'\nimport { PLUGIN_NAME } from '@/shared/constants.js'\nimport { translations } from '@/shared/translations/index.js'\nimport type { OpenApiPluginOptions } from '@/shared/types/index.js'\n\nconst CLI_COMMAND = 'openapi:generate'\n\nconst resolveCommandPath = (): string => {\n const selfUrl = new URL(import.meta.url)\n const ext = selfUrl.pathname.endsWith('.ts') ? '.ts' : '.js'\n return `${fileURLToPath(new URL(`./cli/generateSpec${ext}`, selfUrl))}#generateSpecCommand`\n}\n\nexport const openapi = definePlugin<OpenApiPluginOptions>({\n slug: PLUGIN_NAME,\n plugin: ({ config, options, plugins }) => {\n const resolved = resolveOptions(options)\n for (const entity of [...(config.collections ?? []), ...(config.globals ?? [])]) readSecurityOverride(entity)\n if (options.enabled === false) return config\n\n const authCollection =\n resolved.interactiveAuth.collection ?? (config.collections ?? []).find((c) => Boolean(c.auth))?.slug ?? 'users'\n const features = buildFeatures({ plugins, resolved })\n\n config.i18n = config.i18n ?? {}\n config.i18n.translations = config.i18n.translations ?? {}\n const supportedKeys = config.i18n.supportedLanguages ? Object.keys(config.i18n.supportedLanguages) : ['en']\n for (const lang of supportedKeys) {\n const pluginEntry = translations[lang as keyof typeof translations]\n if (!pluginEntry) continue\n const typedLang = lang as keyof typeof config.i18n.translations\n config.i18n.translations[typedLang] = {\n ...(config.i18n.translations[typedLang] as Record<string, unknown>),\n [PLUGIN_NAME]: pluginEntry[PLUGIN_NAME],\n } as (typeof config.i18n.translations)[typeof typedLang]\n }\n\n return {\n ...config,\n custom: {\n ...config.custom,\n [PLUGIN_NAME]: resolved,\n },\n cli:\n config.cli === false\n ? config.cli\n : {\n ...config.cli,\n commands: { [CLI_COMMAND]: resolveCommandPath(), ...config.cli?.commands },\n },\n endpoints: [\n ...(config.endpoints ?? []),\n ...(resolved.serve\n ? [\n {\n path: resolved.path,\n method: 'get' as const,\n handler: specHandler(resolved),\n },\n ...(resolved.interactiveAuth.enabled\n ? [\n {\n path: resolved.interactiveAuth.path,\n method: 'post' as const,\n handler: interactiveAuthHandler(authCollection),\n },\n ]\n : []),\n ]\n : []),\n ],\n onInit: async (payload) => {\n await config.onInit?.(payload)\n void reportOpenApiTelemetry({ features, options, payload })\n },\n }\n },\n})\n\nexport { buildOpenApiDocument } from '@/server/spec/build.js'\nexport type { BuildOpenApiInput } from '@/server/spec/build.js'\nexport { toOpenApi30, toOpenApi31 } from '@/server/spec/downconvert.js'\nexport { scalar } from '@/server/ui/scalar.js'\nexport { swaggerUi } from '@/server/ui/swagger.js'\n\nexport type {\n AccessOption,\n BuildContext,\n EntityOpenApiMeta,\n EntityOperation,\n EntitySecurityOverride,\n ExtensionContext,\n FieldOpenApiMeta,\n FilterOptions,\n LocalizedText,\n OpenApiExtension,\n OpenApiInfo,\n OpenApiPluginOptions,\n OpenApiVersion,\n OperationContext,\n OperationFilter,\n OperationKind,\n OperationRule,\n SecurityMarking,\n SecurityOption,\n ServersOption,\n UiPluginOptions,\n} from '@/shared/types/index.js'\n"],"mappings":";;;;;;;;;;;;;AAaA,MAAM,cAAc;AAEpB,MAAM,2BAAmC;CACvC,MAAM,UAAU,IAAI,IAAI,YAAY,GAAG;CACvC,MAAM,MAAM,QAAQ,SAAS,SAAS,KAAK,IAAI,QAAQ;CACvD,OAAO,GAAG,cAAc,IAAI,IAAI,qBAAqB,OAAO,OAAO,CAAC,EAAE;AACxE;AAEA,MAAa,UAAU,aAAmC;CACxD,MAAM;CACN,SAAS,EAAE,QAAQ,SAAS,cAAc;EACxC,MAAM,WAAW,eAAe,OAAO;EACvC,KAAK,MAAM,UAAU,CAAC,GAAI,OAAO,eAAe,CAAC,GAAI,GAAI,OAAO,WAAW,CAAC,CAAE,GAAG,qBAAqB,MAAM;EAC5G,IAAI,QAAQ,YAAY,OAAO,OAAO;EAEtC,MAAM,iBACJ,SAAS,gBAAgB,eAAe,OAAO,eAAe,CAAC,EAAA,CAAG,MAAM,MAAM,QAAQ,EAAE,IAAI,CAAC,CAAC,EAAE,QAAQ;EAC1G,MAAM,WAAW,cAAc;GAAE;GAAS;EAAS,CAAC;EAEpD,OAAO,OAAO,OAAO,QAAQ,CAAC;EAC9B,OAAO,KAAK,eAAe,OAAO,KAAK,gBAAgB,CAAC;EACxD,MAAM,gBAAgB,OAAO,KAAK,qBAAqB,OAAO,KAAK,OAAO,KAAK,kBAAkB,IAAI,CAAC,IAAI;EAC1G,KAAK,MAAM,QAAQ,eAAe;GAChC,MAAM,cAAc,aAAa;GACjC,IAAI,CAAC,aAAa;GAClB,MAAM,YAAY;GAClB,OAAO,KAAK,aAAa,aAAa;IACpC,GAAI,OAAO,KAAK,aAAa;KAC5B,cAAc,YAAY;GAC7B;EACF;EAEA,OAAO;GACL,GAAG;GACH,QAAQ;IACN,GAAG,OAAO;KACT,cAAc;GACjB;GACA,KACE,OAAO,QAAQ,QACX,OAAO,MACP;IACE,GAAG,OAAO;IACV,UAAU;MAAG,cAAc,mBAAmB;KAAG,GAAG,OAAO,KAAK;IAAS;GAC3E;GACN,WAAW,CACT,GAAI,OAAO,aAAa,CAAC,GACzB,GAAI,SAAS,QACT,CACE;IACE,MAAM,SAAS;IACf,QAAQ;IACR,SAAS,YAAY,QAAQ;GAC/B,GACA,GAAI,SAAS,gBAAgB,UACzB,CACE;IACE,MAAM,SAAS,gBAAgB;IAC/B,QAAQ;IACR,SAAS,uBAAuB,cAAc;GAChD,CACF,IACA,CAAC,CACP,IACA,CAAC,CACP;GACA,QAAQ,OAAO,YAAY;IACzB,MAAM,OAAO,SAAS,OAAO;IAC7B,uBAA4B;KAAE;KAAU;KAAS;IAAQ,CAAC;GAC5D;EACF;CACF;AACF,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Endpoint } from "payload";
|
|
2
2
|
type InteractiveAuthHandler = (authCollectionSlug: string) => Endpoint['handler'];
|
|
3
3
|
export declare const interactiveAuthHandler: InteractiveAuthHandler;
|
|
4
|
-
|
|
4
|
+
//# sourceMappingURL=interactiveAuth.d.ts.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const interactiveAuthHandler = (authCollectionSlug) => async (req) => {
|
|
2
|
+
const form = await req.formData?.();
|
|
3
|
+
const username = form?.get("username")?.toString() ?? "";
|
|
4
|
+
const password = form?.get("password")?.toString() ?? "";
|
|
5
|
+
try {
|
|
6
|
+
const result = await req.payload.login({
|
|
7
|
+
collection: authCollectionSlug,
|
|
8
|
+
data: {
|
|
9
|
+
email: username,
|
|
10
|
+
username,
|
|
11
|
+
password
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
return Response.json({
|
|
15
|
+
access_token: result.token,
|
|
16
|
+
token_type: "JWT",
|
|
17
|
+
expires_in: result.exp === void 0 ? void 0 : result.exp - Math.floor(Date.now() / 1e3)
|
|
18
|
+
});
|
|
19
|
+
} catch {
|
|
20
|
+
return Response.json({ error: "invalid_grant" }, { status: 400 });
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
export { interactiveAuthHandler };
|
|
24
|
+
|
|
25
|
+
//# sourceMappingURL=interactiveAuth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactiveAuth.js","names":[],"sources":["../../../src/server/endpoints/interactiveAuth.ts"],"sourcesContent":["import type { Endpoint } from 'payload'\n\ntype InteractiveAuthHandler = (authCollectionSlug: string) => Endpoint['handler']\n\nexport const interactiveAuthHandler: InteractiveAuthHandler = (authCollectionSlug) => async (req) => {\n const form = await req.formData?.()\n const username = form?.get('username')?.toString() ?? ''\n const password = form?.get('password')?.toString() ?? ''\n\n try {\n const result = await req.payload.login({\n collection: authCollectionSlug,\n data: { email: username, username, password } as never,\n })\n return Response.json({\n access_token: result.token,\n token_type: 'JWT',\n expires_in: result.exp === undefined ? undefined : result.exp - Math.floor(Date.now() / 1000),\n })\n } catch {\n return Response.json({ error: 'invalid_grant' }, { status: 400 })\n }\n}\n"],"mappings":"AAIA,MAAa,0BAAkD,uBAAuB,OAAO,QAAQ;CACnG,MAAM,OAAO,MAAM,IAAI,WAAW;CAClC,MAAM,WAAW,MAAM,IAAI,UAAU,CAAC,EAAE,SAAS,KAAK;CACtD,MAAM,WAAW,MAAM,IAAI,UAAU,CAAC,EAAE,SAAS,KAAK;CAEtD,IAAI;EACF,MAAM,SAAS,MAAM,IAAI,QAAQ,MAAM;GACrC,YAAY;GACZ,MAAM;IAAE,OAAO;IAAU;IAAU;GAAS;EAC9C,CAAC;EACD,OAAO,SAAS,KAAK;GACnB,cAAc,OAAO;GACrB,YAAY;GACZ,YAAY,OAAO,QAAQ,KAAA,IAAY,KAAA,IAAY,OAAO,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;EAC9F,CAAC;CACH,QAAQ;EACN,OAAO,SAAS,KAAK,EAAE,OAAO,gBAAgB,GAAG,EAAE,QAAQ,IAAI,CAAC;CAClE;AACF"}
|