@tc-libs/seo-generator 3.8.0 → 3.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +187 -0
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# @tc-libs/seo-generator
|
|
2
|
+
|
|
3
|
+
Modulo NestJS per generare metadati SEO (title e description) in piu lingue tramite OpenAI, usando un prompt template letto da storage S3.
|
|
4
|
+
|
|
5
|
+
## Funzionalita
|
|
6
|
+
|
|
7
|
+
- Integrazione con OpenAI Chat Completions
|
|
8
|
+
- Generazione metadata multilingua
|
|
9
|
+
- Prompt template caricato da S3 con cache in memoria (TTL 30 minuti)
|
|
10
|
+
- Tracciamento costo totale e breakdown per lingua
|
|
11
|
+
- Controller admin pronto all'uso per endpoint di generazione
|
|
12
|
+
|
|
13
|
+
## Installazione
|
|
14
|
+
|
|
15
|
+
Dipendenze principali usate dal modulo:
|
|
16
|
+
|
|
17
|
+
- @nestjs/common
|
|
18
|
+
- openai
|
|
19
|
+
- @tc-libs/storage
|
|
20
|
+
- @tc-libs/database
|
|
21
|
+
- @tc-libs/authentication
|
|
22
|
+
- @tc-libs/response
|
|
23
|
+
|
|
24
|
+
## Configurazione modulo
|
|
25
|
+
|
|
26
|
+
### register
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
import { Module } from '@nestjs/common';
|
|
30
|
+
import { StorageAwsS3Module } from '@tc-libs/storage';
|
|
31
|
+
import { SeoGeneratorModule } from '@tc-libs/seo-generator';
|
|
32
|
+
|
|
33
|
+
@Module({
|
|
34
|
+
imports: [
|
|
35
|
+
StorageAwsS3Module.register({
|
|
36
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
37
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
38
|
+
region: process.env.AWS_REGION!,
|
|
39
|
+
bucket: process.env.AWS_S3_BUCKET!,
|
|
40
|
+
}),
|
|
41
|
+
SeoGeneratorModule.register(
|
|
42
|
+
{
|
|
43
|
+
apiKey: process.env.OPENAI_API_KEY!,
|
|
44
|
+
models: {
|
|
45
|
+
mini: {
|
|
46
|
+
code: 'gpt-4.1-mini',
|
|
47
|
+
price: {
|
|
48
|
+
input: 0.15,
|
|
49
|
+
cachedInput: 0.075,
|
|
50
|
+
output: 0.6,
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
prompt: {
|
|
55
|
+
fileName: 'seo-generator.prompt.txt',
|
|
56
|
+
folder: 'prompts',
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
true,
|
|
60
|
+
),
|
|
61
|
+
],
|
|
62
|
+
})
|
|
63
|
+
export class AppModule {}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### registerAsync
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
import { Module } from '@nestjs/common';
|
|
70
|
+
import { ConfigModule, ConfigService } from '@nestjs/config';
|
|
71
|
+
import { SeoGeneratorModule } from '@tc-libs/seo-generator';
|
|
72
|
+
|
|
73
|
+
@Module({
|
|
74
|
+
imports: [
|
|
75
|
+
ConfigModule.forRoot({ isGlobal: true }),
|
|
76
|
+
SeoGeneratorModule.registerAsync(
|
|
77
|
+
{
|
|
78
|
+
imports: [ConfigModule],
|
|
79
|
+
inject: [ConfigService],
|
|
80
|
+
useFactory: (config: ConfigService) => ({
|
|
81
|
+
apiKey: config.getOrThrow<string>('OPENAI_API_KEY'),
|
|
82
|
+
models: {
|
|
83
|
+
mini: {
|
|
84
|
+
code: config.get<string>('SEO_OPENAI_MODEL') ?? 'gpt-4.1-mini',
|
|
85
|
+
price: {
|
|
86
|
+
input: Number(config.get<string>('SEO_PRICE_INPUT') ?? '0.15'),
|
|
87
|
+
cachedInput: Number(
|
|
88
|
+
config.get<string>('SEO_PRICE_CACHED_INPUT') ?? '0.075',
|
|
89
|
+
),
|
|
90
|
+
output: Number(config.get<string>('SEO_PRICE_OUTPUT') ?? '0.6'),
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
prompt: {
|
|
95
|
+
fileName: config.getOrThrow<string>('SEO_PROMPT_FILE_NAME'),
|
|
96
|
+
folder: config.getOrThrow<string>('SEO_PROMPT_FOLDER'),
|
|
97
|
+
},
|
|
98
|
+
}),
|
|
99
|
+
},
|
|
100
|
+
true,
|
|
101
|
+
),
|
|
102
|
+
],
|
|
103
|
+
})
|
|
104
|
+
export class AppModule {}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Uso service
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
import { Injectable } from '@nestjs/common';
|
|
111
|
+
import { SeoGeneratorService } from '@tc-libs/seo-generator';
|
|
112
|
+
|
|
113
|
+
@Injectable()
|
|
114
|
+
export class ProductSeoFacade {
|
|
115
|
+
constructor(private readonly seoGenerator: SeoGeneratorService) {}
|
|
116
|
+
|
|
117
|
+
async generateForProduct(productName: string, description: string) {
|
|
118
|
+
return this.seoGenerator.generateSeoMetadata(productName, description, [
|
|
119
|
+
'it',
|
|
120
|
+
'en',
|
|
121
|
+
]);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Risposta del service:
|
|
127
|
+
|
|
128
|
+
```ts
|
|
129
|
+
type SeoGeneratorResult = {
|
|
130
|
+
seo: {
|
|
131
|
+
title: Record<string, string>;
|
|
132
|
+
description: Record<string, string>;
|
|
133
|
+
};
|
|
134
|
+
cost: number;
|
|
135
|
+
breakdown: Array<{
|
|
136
|
+
language: string;
|
|
137
|
+
inputTokens: number;
|
|
138
|
+
cachedInputTokens: number;
|
|
139
|
+
outputTokens: number;
|
|
140
|
+
cost: number;
|
|
141
|
+
}>;
|
|
142
|
+
};
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Endpoint admin
|
|
146
|
+
|
|
147
|
+
Il pacchetto esporta anche `SeoGeneratorAdminController` con route:
|
|
148
|
+
|
|
149
|
+
- `POST /v1/seo-generator/generate`
|
|
150
|
+
|
|
151
|
+
Payload:
|
|
152
|
+
|
|
153
|
+
```json
|
|
154
|
+
{
|
|
155
|
+
"entity": "Nome prodotto",
|
|
156
|
+
"context": "Descrizione completa del prodotto",
|
|
157
|
+
"languages": ["it", "en"]
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Validazioni DTO:
|
|
162
|
+
|
|
163
|
+
- `entity`: stringa obbligatoria
|
|
164
|
+
- `context`: stringa obbligatoria
|
|
165
|
+
- `languages`: array obbligatorio di stringhe
|
|
166
|
+
|
|
167
|
+
## Prompt template
|
|
168
|
+
|
|
169
|
+
Il template viene letto da S3 (`prompt.fileName`, `prompt.folder`) e mantenuto in cache per 30 minuti.
|
|
170
|
+
|
|
171
|
+
Il contenuto del prompt deve forzare un output JSON con struttura:
|
|
172
|
+
|
|
173
|
+
```json
|
|
174
|
+
{
|
|
175
|
+
"title": "...",
|
|
176
|
+
"description": "..."
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Export disponibili
|
|
181
|
+
|
|
182
|
+
- `SeoGeneratorModule`
|
|
183
|
+
- `SeoGeneratorService`
|
|
184
|
+
- `SeoGeneratorAdminController`
|
|
185
|
+
- `SeoGeneratorGenerateAdminDto`
|
|
186
|
+
- `SeoGeneratorSerialization`
|
|
187
|
+
- Tipi opzioni modulo (`SeoGeneratorModuleOptions`, token `SEO_GENERATOR_CONFIG_OPTIONS`)
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tc-libs/seo-generator",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.9.0",
|
|
4
4
|
"dependencies": {
|
|
5
5
|
"@nestjs/common": "^11.0.12",
|
|
6
6
|
"@nestjs/swagger": "^11.1.0",
|
|
7
|
-
"@tc-libs/authentication": "3.
|
|
8
|
-
"@tc-libs/response": "3.
|
|
7
|
+
"@tc-libs/authentication": "3.9.0",
|
|
8
|
+
"@tc-libs/response": "3.9.0",
|
|
9
9
|
"class-validator": "^0.14.1",
|
|
10
|
-
"@tc-libs/database": "3.
|
|
10
|
+
"@tc-libs/database": "3.9.0",
|
|
11
11
|
"openai": "^6.33.0",
|
|
12
|
-
"@tc-libs/storage": "3.
|
|
12
|
+
"@tc-libs/storage": "3.9.0",
|
|
13
13
|
"tslib": "^2.8.1"
|
|
14
14
|
},
|
|
15
15
|
"type": "commonjs",
|