payload-ai 0.0.1 → 0.0.4

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.
Files changed (80) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +126 -22
  3. package/dev/package.json +6 -4
  4. package/dev/src/collections/Examples.ts +19 -2
  5. package/dev/src/collections/ExamplesWithVersions.ts +31 -0
  6. package/dev/src/payload.config.ts +19 -7
  7. package/dist/access/admins.d.ts +4 -0
  8. package/dist/access/admins.js +12 -0
  9. package/dist/access/admins.js.map +1 -0
  10. package/dist/access/adminsOrPublished.d.ts +2 -0
  11. package/dist/access/adminsOrPublished.js +18 -0
  12. package/dist/access/adminsOrPublished.js.map +1 -0
  13. package/dist/access/anyone.d.ts +2 -0
  14. package/dist/access/anyone.js +6 -0
  15. package/dist/access/anyone.js.map +1 -0
  16. package/dist/access/checkRole.d.ts +1 -0
  17. package/dist/access/checkRole.js +18 -0
  18. package/dist/access/checkRole.js.map +1 -0
  19. package/dist/aiTranslate.d.ts +4 -2
  20. package/dist/aiTranslate.js +95 -153
  21. package/dist/aiTranslate.js.map +1 -1
  22. package/dist/components/Metadata/index.d.ts +2 -0
  23. package/dist/components/Metadata/index.js +101 -0
  24. package/dist/components/Metadata/index.js.map +1 -0
  25. package/dist/components/Translator/index.js +16 -14
  26. package/dist/components/Translator/index.js.map +1 -1
  27. package/dist/deepCompareAndMerge.d.ts +5 -0
  28. package/dist/deepCompareAndMerge.js +96 -0
  29. package/dist/deepCompareAndMerge.js.map +1 -0
  30. package/dist/generateImage.d.ts +1 -0
  31. package/dist/generateImage.js +80 -0
  32. package/dist/generateImage.js.map +1 -0
  33. package/dist/generateText.d.ts +5 -0
  34. package/dist/generateText.js +90 -0
  35. package/dist/generateText.js.map +1 -0
  36. package/dist/handleTranslate.d.ts +2 -2
  37. package/dist/handleTranslate.js +35 -8
  38. package/dist/handleTranslate.js.map +1 -1
  39. package/dist/index.d.ts +1 -0
  40. package/dist/index.js +4 -1
  41. package/dist/index.js.map +1 -1
  42. package/dist/plugin.js +31 -28
  43. package/dist/plugin.js.map +1 -1
  44. package/dist/seoTools.d.ts +2 -0
  45. package/dist/seoTools.js +135 -0
  46. package/dist/seoTools.js.map +1 -0
  47. package/dist/stringTranslations.d.ts +3 -0
  48. package/dist/stringTranslations.js +174 -0
  49. package/dist/stringTranslations.js.map +1 -0
  50. package/dist/translateTextAndObjects copy.d.ts +1 -0
  51. package/dist/translateTextAndObjects copy.js +84 -0
  52. package/dist/translateTextAndObjects copy.js.map +1 -0
  53. package/dist/translateTextAndObjects.d.ts +1 -0
  54. package/dist/translateTextAndObjects.js +107 -0
  55. package/dist/translateTextAndObjects.js.map +1 -0
  56. package/package.json +3 -3
  57. package/src/access/admins.ts +11 -0
  58. package/src/access/adminsOrPublished.ts +16 -0
  59. package/src/access/anyone.ts +3 -0
  60. package/src/access/checkRole.ts +16 -0
  61. package/src/aiTranslate.ts +79 -140
  62. package/src/components/Metadata/index.scss +10 -0
  63. package/src/components/Metadata/index.tsx +59 -0
  64. package/src/components/Translator/index.tsx +7 -8
  65. package/src/deepCompareAndMerge.ts +77 -0
  66. package/src/generateImage.ts +39 -0
  67. package/src/generateText.ts +27 -0
  68. package/src/handleTranslate.ts +23 -27
  69. package/src/index.ts +2 -0
  70. package/src/plugin.ts +55 -42
  71. package/src/seoTools.ts +75 -0
  72. package/src/stringTranslations.ts +145 -0
  73. package/src/translateTextAndObjects copy.ts +77 -0
  74. package/src/translateTextAndObjects.ts +64 -0
  75. package/.github/workflows/publish.yml +0 -21
  76. package/.github/workflows/test.yml +0 -20
  77. package/dist/newCollection.d.ts +0 -3
  78. package/dist/newCollection.js +0 -16
  79. package/dist/newCollection.js.map +0 -1
  80. package/src/newCollection.ts +0 -16
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2023 Payload
3
+ Copyright (c) 2024 wirewire
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,12 +1,133 @@
1
- # Payload Plugin Template
1
+ # Payload AI
2
2
 
3
- Translate content to different languages using GPT.
3
+ Translate content to different languages using OpenAI's GPT.
4
4
 
5
- Planned features:
5
+
6
+ ### How to install the plugin
7
+
8
+ Install via npm:
9
+
10
+
11
+ ```
12
+ npm install payload-ai
13
+ ```
14
+
15
+ Or yarn:
16
+ ```
17
+ yarn add payload-ai
18
+ ```
19
+
20
+ To install the plugin, simply add it to your payload.config() in the Plugin array.
21
+
22
+ ```ts
23
+ import payloadAi from 'payload-ai';
24
+
25
+ export const config = buildConfig({
26
+ plugins: [
27
+ // You can pass options to the plugin
28
+ payloadAi({
29
+ enabled: true,
30
+ }),
31
+ ]
32
+ });
33
+ ```
34
+
35
+ ### Collection translation
36
+
37
+ Add the `collections` where you want to enable the translation and the `fields`. It will translate each field (also nested fields) on every update of the default language.
38
+
39
+ ```ts
40
+ plugins: [
41
+ aiTranslatorPlugin({
42
+ enabled: true,
43
+ collections: {
44
+ examples: {
45
+ // prompts: [myCollectionPrompt]
46
+ fields: [
47
+ 'stringText',
48
+ 'richText',
49
+ {
50
+ "fieldWithCustomPrompt":
51
+ {prompt: myPromptFunction}
52
+ }
53
+ ],
54
+ },
55
+ },
56
+ }),
57
+ ],
58
+ ```
59
+
60
+ #### Use in hooks
61
+
62
+ TODO: add documentation
63
+
64
+ myCollectionPrompt = ({source}) => {
65
+
66
+ source()
67
+
68
+ return
69
+ }
70
+
71
+ #### Custom prompts by Field
72
+
73
+ Use the `prompt` function for each field to use a customized prompt. The function will allow you to use the following
74
+
75
+
76
+ - `req`: Request
77
+ - `doc` Document in languages
78
+ - `previousDoc` Old document (only available on Update)
79
+ - `targetDoc` The old target document
80
+ - `collectionOptions`
81
+ - `language`
82
+ - translatorConfig
83
+ language: string,
84
+ sourceLanguage?: string,
85
+
86
+ - targetField
87
+ - sourceField
88
+
89
+
90
+ ```jsx
91
+ customPrompt = ({sourceField}) => `Translate ${sourceField} to ${targetLanguage}.`
92
+ ```
93
+
94
+ ### Use with [payload-seo](https://payloadcms.com/docs/plugins/seo)
95
+
96
+ ```jsx
97
+
98
+
99
+ import {generateTitle, generateDescription } from "payload-ai";
100
+
101
+ seo({
102
+ collections: ['examples'],
103
+ // uploadsCollection: 'media',
104
+ generateTitle: generateTitle,
105
+ generateDescription: ({ doc }) => generateDescription,
106
+ });
107
+ ```
108
+
109
+ ### String translation
110
+
111
+ Use this to provide a [backend](https://github.com/i18next/i18next-http-backend) for [i18next](https://www.i18next.com) string translations.
112
+
113
+
114
+ ```jsx
115
+ plugins: [
116
+ aiTranslatorPlugin({
117
+ enabled: true,
118
+ stringTranslation: {
119
+ enabled: true
120
+ }
121
+ }),
122
+ ],
123
+ ```
124
+
125
+ ### Generate SEO
126
+
127
+
128
+ ### Planned features
6
129
 
7
130
  - generate image alt text from GPT
8
- - generate by field
9
- - string translation using i18next
10
131
  - generate SEO Text
11
132
  - generate structured content
12
133
  - custom access control
@@ -20,26 +141,9 @@ To build your own Payload plugin, all you need is:
20
141
  * An understanding of the basic Payload concepts
21
142
  * And some JavaScript/Typescript experience
22
143
 
23
- ## Background
24
-
25
- Here is a short recap on how to integrate plugins with Payload, to learn more visit the [plugin overview page](https://payloadcms.com/docs/plugins/overview).
26
144
 
27
- ### How to install a plugin
28
145
 
29
- To install any plugin, simply add it to your payload.config() in the Plugin array.
30
-
31
- ```ts
32
- import samplePlugin from 'sample-plugin';
33
146
 
34
- export const config = buildConfig({
35
- plugins: [
36
- // You can pass options to the plugin
37
- samplePlugin({
38
- enabled: true,
39
- }),
40
- ]
41
- });
42
- ```
43
147
 
44
148
  ### Initialization
45
149
 
package/dev/package.json CHANGED
@@ -17,13 +17,15 @@
17
17
  },
18
18
  "dependencies": {
19
19
  "@payloadcms/bundler-webpack": "^1.0.0",
20
- "@payloadcms/db-mongodb": "^1.0.0",
20
+ "@payloadcms/db-mongodb": "^1.2.0",
21
21
  "@payloadcms/plugin-cloud": "^2.0.0",
22
- "@payloadcms/richtext-slate": "^1.0.0",
22
+ "@payloadcms/plugin-seo": "^1.0.15",
23
+ "@payloadcms/richtext-lexical": "^0.5.1",
24
+ "@payloadcms/richtext-slate": "^1.3.1",
23
25
  "cross-env": "^7.0.3",
24
26
  "dotenv": "^8.2.0",
25
27
  "express": "^4.17.1",
26
- "payload": "^2.0.0"
28
+ "payload": "^2.7.0"
27
29
  },
28
30
  "devDependencies": {
29
31
  "@types/express": "^4.17.9",
@@ -32,4 +34,4 @@
32
34
  "ts-node": "^9.1.1",
33
35
  "typescript": "^4.8.4"
34
36
  }
35
- }
37
+ }
@@ -1,17 +1,34 @@
1
+ import { lexicalEditor } from '@payloadcms/richtext-lexical'
1
2
  import { CollectionConfig } from 'payload/types'
2
3
 
3
4
  // Example Collection - For reference only, this must be added to payload.config.ts to be used.
4
5
  const Examples: CollectionConfig = {
5
6
  slug: 'examples',
6
7
  admin: {
7
- useAsTitle: 'someField',
8
+ useAsTitle: 'title',
8
9
  },
9
10
  fields: [
10
11
  {
11
- name: 'richText',
12
+ name: 'title',
12
13
  type: 'text',
13
14
  localized: true,
14
15
  },
16
+ {
17
+ name: 'contentRichText',
18
+ type: 'richText',
19
+ editor: lexicalEditor({}),
20
+ localized: true,
21
+ },
22
+ {
23
+ name: 'longText',
24
+ type: 'code',
25
+ localized: true,
26
+ },
27
+ {
28
+ name: 'doNotAutoTranslate',
29
+ type: 'code',
30
+ localized: true,
31
+ },
15
32
  ],
16
33
  }
17
34
 
@@ -0,0 +1,31 @@
1
+ import { CollectionConfig } from 'payload/types'
2
+
3
+ // Example Collection - For reference only, this must be added to payload.config.ts to be used.
4
+ const ExamplesWithVersions: CollectionConfig = {
5
+ slug: 'examples-with-versions',
6
+ admin: {
7
+ useAsTitle: 'title',
8
+ },
9
+ versions: {
10
+ drafts: true,
11
+ },
12
+ fields: [
13
+ {
14
+ name: 'title',
15
+ type: 'text',
16
+ localized: true,
17
+ },
18
+ {
19
+ name: 'longText',
20
+ type: 'code',
21
+ localized: true,
22
+ },
23
+ {
24
+ name: 'doNotAutoTranslate',
25
+ type: 'code',
26
+ localized: true,
27
+ },
28
+ ],
29
+ }
30
+
31
+ export default ExamplesWithVersions
@@ -4,8 +4,11 @@ import Users from './collections/Users'
4
4
  import Examples from './collections/Examples'
5
5
  import { mongooseAdapter } from '@payloadcms/db-mongodb'
6
6
  import { webpackBundler } from '@payloadcms/bundler-webpack'
7
- import { slateEditor } from '@payloadcms/richtext-slate'
8
- import { aiTranslatorPlugin } from '../../src/index'
7
+ // import { slateEditor } from '@payloadcms/richtext-slate'
8
+ import { lexicalEditor } from '@payloadcms/richtext-lexical'
9
+ import { aiTranslatorPlugin, generateDescription, generateTitle } from '../../src/index'
10
+ import ExamplesWithVersions from './collections/ExamplesWithVersions'
11
+ import seo from '@payloadcms/plugin-seo'
9
12
 
10
13
  export default buildConfig({
11
14
  admin: {
@@ -27,10 +30,11 @@ export default buildConfig({
27
30
  return newConfig
28
31
  },
29
32
  },
30
- editor: slateEditor({}),
31
- collections: [Examples, Users],
33
+ editor: lexicalEditor({}),
34
+ // editor: slateEditor({}),
35
+ collections: [Examples, ExamplesWithVersions, Users],
32
36
  localization: {
33
- locales: ['en', 'es', 'de'],
37
+ locales: ['en', 'de', 'ja' /* 'es','fr', 'it', 'ja'*/],
34
38
  defaultLocale: 'en',
35
39
  fallback: true,
36
40
  },
@@ -45,11 +49,19 @@ export default buildConfig({
45
49
  enabled: true,
46
50
  collections: {
47
51
  examples: {
48
- fields: ['richText'],
49
- // adapter: theAdapterToUse, // see docs for the adapter you want to use
52
+ fields: ['title', 'longText', 'jsonContent', 'contentRichText'],
53
+ },
54
+ 'examples-with-versions': {
55
+ fields: ['title', 'longText', 'jsonContent'],
50
56
  },
51
57
  },
52
58
  }),
59
+ seo({
60
+ collections: ['examples'],
61
+ // uploadsCollection: 'media',
62
+ generateTitle: generateTitle,
63
+ generateDescription: generateDescription,
64
+ }),
53
65
  ],
54
66
  db: mongooseAdapter({
55
67
  url: process.env.DATABASE_URI,
@@ -0,0 +1,4 @@
1
+ import type { AccessArgs } from 'payload/config';
2
+ type isAdmin = (args: AccessArgs<unknown, any>) => boolean;
3
+ export declare const admins: isAdmin;
4
+ export {};
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.admins = void 0;
4
+ var checkRole_1 = require("./checkRole");
5
+ var admins = function (_a) {
6
+ var user = _a.req.user;
7
+ if (!user)
8
+ return false;
9
+ return (0, checkRole_1.checkRole)(['admin'], user);
10
+ };
11
+ exports.admins = admins;
12
+ //# sourceMappingURL=admins.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admins.js","sourceRoot":"","sources":["../../src/access/admins.ts"],"names":[],"mappings":";;;AAEA,yCAAuC;AAKhC,IAAM,MAAM,GAAY,UAAC,EAAiB;QAAR,IAAI,cAAA;IAC3C,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAA;IACvB,OAAO,IAAA,qBAAS,EAAC,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,CAAA;AACnC,CAAC,CAAA;AAHY,QAAA,MAAM,UAGlB"}
@@ -0,0 +1,2 @@
1
+ import type { Access } from 'payload/config';
2
+ export declare const adminsOrPublished: Access;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.adminsOrPublished = void 0;
4
+ var checkRole_1 = require("./checkRole");
5
+ var adminsOrPublished = function (_a) {
6
+ var user = _a.req.user;
7
+ if (user && (0, checkRole_1.checkRole)(['admin'], user)) {
8
+ return true;
9
+ }
10
+ return true;
11
+ return {
12
+ _status: {
13
+ equals: 'published',
14
+ },
15
+ };
16
+ };
17
+ exports.adminsOrPublished = adminsOrPublished;
18
+ //# sourceMappingURL=adminsOrPublished.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adminsOrPublished.js","sourceRoot":"","sources":["../../src/access/adminsOrPublished.ts"],"names":[],"mappings":";;;AAEA,yCAAuC;AAEhC,IAAM,iBAAiB,GAAW,UAAC,EAAiB;QAAR,IAAI,cAAA;IACrD,IAAI,IAAI,IAAI,IAAA,qBAAS,EAAC,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE;QACtC,OAAO,IAAI,CAAA;KACZ;IAED,OAAO,IAAI,CAAA;IACX,OAAO;QACL,OAAO,EAAE;YACP,MAAM,EAAE,WAAW;SACpB;KACF,CAAA;AACH,CAAC,CAAA;AAXY,QAAA,iBAAiB,qBAW7B"}
@@ -0,0 +1,2 @@
1
+ import type { Access } from 'payload/config';
2
+ export declare const anyone: Access;
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.anyone = void 0;
4
+ var anyone = function () { return true; };
5
+ exports.anyone = anyone;
6
+ //# sourceMappingURL=anyone.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anyone.js","sourceRoot":"","sources":["../../src/access/anyone.ts"],"names":[],"mappings":";;;AAEO,IAAM,MAAM,GAAW,cAAM,OAAA,IAAI,EAAJ,CAAI,CAAA;AAA3B,QAAA,MAAM,UAAqB"}
@@ -0,0 +1 @@
1
+ export declare const checkRole: (allRoles: any, user?: any) => boolean;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ //import type { User } from '../../payload-types'
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.checkRole = void 0;
5
+ var checkRole = function (allRoles /* User['roles'] = [] */, user) {
6
+ if (user) {
7
+ if (allRoles.some(function (role) {
8
+ var _a;
9
+ return (_a = user === null || user === void 0 ? void 0 : user.roles) === null || _a === void 0 ? void 0 : _a.some(function (individualRole) {
10
+ return individualRole === role;
11
+ });
12
+ }))
13
+ return true;
14
+ }
15
+ return false;
16
+ };
17
+ exports.checkRole = checkRole;
18
+ //# sourceMappingURL=checkRole.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkRole.js","sourceRoot":"","sources":["../../src/access/checkRole.ts"],"names":[],"mappings":";AAAA,iDAAiD;;;AAE1C,IAAM,SAAS,GAAG,UAAC,QAAa,CAAC,wBAAwB,EAAE,IAAU;IAC1E,IAAI,IAAI,EAAE;QACR,IACE,QAAQ,CAAC,IAAI,CAAC,UAAC,IAAS;;YACtB,OAAO,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,KAAK,0CAAE,IAAI,CAAC,UAAC,cAAmB;gBAC3C,OAAO,cAAc,KAAK,IAAI,CAAA;YAChC,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC;YAEF,OAAO,IAAI,CAAA;KACd;IAED,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AAbY,QAAA,SAAS,aAarB"}
@@ -1,5 +1,7 @@
1
1
  import type { CollectionAfterChangeHook } from 'payload/types';
2
- declare const aiTranslate: ({ collection }: {
2
+ declare const aiTranslateHook: ({ collectionOptions, collection }: {
3
+ collectionOptions: any;
3
4
  collection: object;
4
5
  }, fallback?: string) => CollectionAfterChangeHook;
5
- export default aiTranslate;
6
+ export default aiTranslateHook;
7
+ export declare function translateCollection({ req, doc, collection, previousDoc, context, collectionOptions, onlyMissing, }: any): Promise<void>;