@olmocms/front 0.1.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.
Files changed (47) hide show
  1. package/README.md +277 -0
  2. package/dist/chunk-3DP2A2OG.js +52 -0
  3. package/dist/chunk-3DP2A2OG.js.map +1 -0
  4. package/dist/chunk-GQITFXCV.js +66 -0
  5. package/dist/chunk-GQITFXCV.js.map +1 -0
  6. package/dist/chunk-JISDMUJ3.js +79 -0
  7. package/dist/chunk-JISDMUJ3.js.map +1 -0
  8. package/dist/chunk-RG54JLA2.js +61 -0
  9. package/dist/chunk-RG54JLA2.js.map +1 -0
  10. package/dist/cli/index.js +344 -0
  11. package/dist/client/index.cjs +105 -0
  12. package/dist/client/index.cjs.map +1 -0
  13. package/dist/client/index.d.cts +5 -0
  14. package/dist/client/index.d.ts +5 -0
  15. package/dist/client/index.js +11 -0
  16. package/dist/client/index.js.map +1 -0
  17. package/dist/components/index.cjs +113 -0
  18. package/dist/components/index.cjs.map +1 -0
  19. package/dist/components/index.d.cts +46 -0
  20. package/dist/components/index.d.ts +46 -0
  21. package/dist/components/index.js +79 -0
  22. package/dist/components/index.js.map +1 -0
  23. package/dist/index.cjs +370 -0
  24. package/dist/index.cjs.map +1 -0
  25. package/dist/index.d.cts +51 -0
  26. package/dist/index.d.ts +51 -0
  27. package/dist/index.js +110 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/jsonld/index.cjs +88 -0
  30. package/dist/jsonld/index.cjs.map +1 -0
  31. package/dist/jsonld/index.d.cts +33 -0
  32. package/dist/jsonld/index.d.ts +33 -0
  33. package/dist/jsonld/index.js +13 -0
  34. package/dist/jsonld/index.js.map +1 -0
  35. package/dist/middleware/index.cjs +94 -0
  36. package/dist/middleware/index.cjs.map +1 -0
  37. package/dist/middleware/index.d.cts +10 -0
  38. package/dist/middleware/index.d.ts +10 -0
  39. package/dist/middleware/index.js +11 -0
  40. package/dist/middleware/index.js.map +1 -0
  41. package/dist/seo/index.cjs +76 -0
  42. package/dist/seo/index.cjs.map +1 -0
  43. package/dist/seo/index.d.cts +45 -0
  44. package/dist/seo/index.d.ts +45 -0
  45. package/dist/seo/index.js +7 -0
  46. package/dist/seo/index.js.map +1 -0
  47. package/package.json +73 -0
package/README.md ADDED
@@ -0,0 +1,277 @@
1
+ # @olmocms/front
2
+
3
+ Shared utilities, React components, SEO helpers, middleware, and CLI scaffold tool for Olmo CMS Next.js frontends.
4
+
5
+ ---
6
+
7
+ ## Table of contents
8
+
9
+ - [Package entries](#package-entries)
10
+ - [Installation](#installation)
11
+ - [Local development (watch mode)](#local-development-watch-mode)
12
+ - [Publishing to npm](#publishing-to-npm)
13
+ - [Versioning](#versioning)
14
+ - [CLI — olmo-front](#cli--olmo-front)
15
+ - [Entry point reference](#entry-point-reference)
16
+
17
+ ---
18
+
19
+ ## Package entries
20
+
21
+ | Entry | What it exports |
22
+ |---|---|
23
+ | `@olmocms/front` | Re-exports everything |
24
+ | `@olmocms/front/client` | `getting()` — typed API fetch helper |
25
+ | `@olmocms/front/seo` | `setSeoData()` — maps Olmo API SEO payload to Next.js `Metadata` |
26
+ | `@olmocms/front/jsonld` | `buildBreadcrumb()` and other JSON-LD schema builders |
27
+ | `@olmocms/front/middleware` | `olmoMiddleware()` — injects `x-current-path` header + handles locale redirect |
28
+ | `@olmocms/front/components` | `GtmPage`, `JsonLd` — shared React components |
29
+
30
+ ---
31
+
32
+ ## Installation
33
+
34
+ ```bash
35
+ npm install @olmocms/front
36
+ ```
37
+
38
+ No registry configuration needed — the package is public on npm.
39
+
40
+ ---
41
+
42
+ ## Local development (watch mode)
43
+
44
+ Use this workflow when you are actively developing `@olmocms/front` and want changes to reflect immediately in the consuming Next.js project.
45
+
46
+ ### Step 1 — Link the package locally
47
+
48
+ In the consuming project's `package.json`, use a local `file:` reference:
49
+
50
+ ```json
51
+ "dependencies": {
52
+ "@olmocms/front": "file:../olmo-front"
53
+ }
54
+ ```
55
+
56
+ Then run:
57
+
58
+ ```bash
59
+ npm install
60
+ ```
61
+
62
+ ### Step 2 — Start the watch build
63
+
64
+ In `olmo-front/`:
65
+
66
+ ```bash
67
+ npm run dev
68
+ ```
69
+
70
+ This runs `tsup --watch`, which rebuilds `dist/` on every file change (ESM + CJS + type declarations).
71
+
72
+ ### Step 3 — Start the consuming project
73
+
74
+ In `front.olmo/` (or any project consuming the package):
75
+
76
+ ```bash
77
+ npm run dev
78
+ ```
79
+
80
+ Next.js will pick up changes from `dist/` on the next page reload. A full `npm run dev` restart is sometimes needed after major structural changes (e.g. adding a new entry point).
81
+
82
+ ### Switching back to the published version
83
+
84
+ When done developing and after publishing a new version:
85
+
86
+ ```json
87
+ "@olmocms/front": "^0.1.0"
88
+ ```
89
+
90
+ Then run `npm install`.
91
+
92
+ ---
93
+
94
+ ## Publishing to npm
95
+
96
+ ### Prerequisites
97
+
98
+ - npm account with access to the `@olmocms` org
99
+ - npm auth token (Publish scope) stored in `.npmrc`
100
+
101
+ ### Step 1 — Set up `.npmrc`
102
+
103
+ ```bash
104
+ cp .npmrc.example .npmrc
105
+ ```
106
+
107
+ Replace `YOUR_NPM_TOKEN` with a token from **https://www.npmjs.com/settings/\<username\>/tokens**.
108
+
109
+ ### Step 2 — Build
110
+
111
+ ```bash
112
+ npm run build
113
+ ```
114
+
115
+ Produces:
116
+ - `dist/*.js` — ESM bundles
117
+ - `dist/*.cjs` — CommonJS bundles
118
+ - `dist/*.d.ts` — TypeScript declarations
119
+ - `dist/cli/index.js` — CLI binary
120
+
121
+ ### Step 3 — Publish
122
+
123
+ ```bash
124
+ npm publish
125
+ ```
126
+
127
+ The `publishConfig.access: "public"` in `package.json` ensures it publishes as a public scoped package.
128
+
129
+ ### Step 4 — Verify
130
+
131
+ Check **https://www.npmjs.com/package/@olmocms/front** for the new version.
132
+
133
+ ---
134
+
135
+ ## Versioning
136
+
137
+ Follow semantic versioning (`MAJOR.MINOR.PATCH`):
138
+
139
+ | Change type | Version bump | Example |
140
+ |---|---|---|
141
+ | Breaking API change | MAJOR | `0.x.x` → `1.0.0` |
142
+ | New entry point or new export | MINOR | `0.1.0` → `0.2.0` |
143
+ | Bug fix, internal refactor | PATCH | `0.1.0` → `0.1.1` |
144
+
145
+ ```bash
146
+ npm version patch # 0.1.0 → 0.1.1
147
+ npm version minor # 0.1.0 → 0.2.0
148
+ npm version major # 0.1.0 → 1.0.0
149
+ ```
150
+
151
+ Then:
152
+
153
+ ```bash
154
+ npm run build && npm publish
155
+ ```
156
+
157
+ npm does not allow overwriting an existing version — always increment before publishing.
158
+
159
+ ---
160
+
161
+ ## CLI — olmo-front
162
+
163
+ The package ships a CLI binary installed as `olmo-front`.
164
+
165
+ ### Usage
166
+
167
+ ```bash
168
+ npx olmo-front init
169
+ ```
170
+
171
+ ### What it scaffolds
172
+
173
+ The `init` command creates the standard `src/app/[locale]/` route structure for a new Olmo Next.js project:
174
+
175
+ ```
176
+ src/
177
+ app/
178
+ [locale]/
179
+ (website)/
180
+ page.tsx ← Home
181
+ content.tsx
182
+ layout.tsx
183
+ contatti/
184
+ lavora-con-noi/
185
+ news/
186
+ [slug]/
187
+ prodotti/
188
+ [slug]/
189
+ case-studies/
190
+ [slug]/
191
+ cookie-policy/
192
+ components/
193
+ Header/
194
+ Header.tsx
195
+ Footer.tsx
196
+ Form/
197
+ Contact.tsx
198
+ Newsletter.tsx
199
+ Workwithus.tsx
200
+ i18n/
201
+ navigation.ts
202
+ routing.ts
203
+ types.d.ts
204
+ ```
205
+
206
+ Scaffold files are minimal stubs that import from `@olmocms/front` and follow the boilerplate conventions.
207
+
208
+ ---
209
+
210
+ ## Entry point reference
211
+
212
+ ### `@olmocms/front/client`
213
+
214
+ ```ts
215
+ import { getting } from '@olmocms/front/client'
216
+
217
+ const data = await getting<MyType>(locale, pathname, 'page')
218
+ ```
219
+
220
+ `getting(locale, path, type?)` — fetches from the Olmo API using `NEXT_PUBLIC_API_URL`. Returns the typed response or `null` on error. Adds the `x-api-key` header from `NEXT_PUBLIC_API_KEY`.
221
+
222
+ ### `@olmocms/front/seo`
223
+
224
+ ```ts
225
+ import { setSeoData } from '@olmocms/front/seo'
226
+
227
+ const metadata = setSeoData({ seo: page.seo, route: page.route })
228
+ ```
229
+
230
+ Maps the Olmo API SEO payload to a Next.js `Metadata` object ready to return from `generateMetadata()`.
231
+
232
+ ### `@olmocms/front/jsonld`
233
+
234
+ ```ts
235
+ import { buildBreadcrumb } from '@olmocms/front/jsonld'
236
+
237
+ buildBreadcrumb([
238
+ { name: 'Home', url: 'https://example.com/it/' },
239
+ { name: 'News', url: 'https://example.com/it/news/' },
240
+ { name: 'Article title', url: 'https://example.com/it/news/article/' },
241
+ ])
242
+ ```
243
+
244
+ Returns a `BreadcrumbList` JSON-LD schema object. Pass it to `<JsonLd schema={...} />`.
245
+
246
+ ### `@olmocms/front/middleware`
247
+
248
+ ```ts
249
+ import { olmoMiddleware } from '@olmocms/front/middleware'
250
+ export default olmoMiddleware(routing)
251
+ ```
252
+
253
+ Wraps `next-intl` routing middleware and injects the `x-current-path` header into every request so Server Components can read the current URL without `usePathname()`.
254
+
255
+ ### `@olmocms/front/components`
256
+
257
+ ```tsx
258
+ import { GtmPage, JsonLd } from '@olmocms/front/components'
259
+
260
+ <GtmPage slug={pathname} lang={locale} name={page.name} template={page.template} />
261
+ <JsonLd schema={buildBreadcrumb([...])} />
262
+ ```
263
+
264
+ - **`GtmPage`** — fires a `virtual_pageview` event to `window.dataLayer` on mount.
265
+ - **`JsonLd`** — renders a `<script type="application/ld+json">` tag with the given schema.
266
+
267
+ ---
268
+
269
+ ## Environment variables
270
+
271
+ | Variable | Required | Description |
272
+ |---|---|---|
273
+ | `NEXT_PUBLIC_API_URL` | Yes | Base URL of the Olmo API (e.g. `https://api.example.com`) |
274
+ | `NEXT_PUBLIC_API_KEY` | Yes | API key sent as `x-api-key` header |
275
+ | `NEXT_PUBLIC_BASE_URL` | Yes | Public URL of the frontend (used in canonical URLs, JSON-LD) |
276
+ | `NEXT_PUBLIC_GTM_ID` | No | Google Tag Manager container ID |
277
+ | `NEXT_PUBLIC_RECAPTCHA_KEY` | No | reCAPTCHA v3 site key (required if using contact/newsletter forms) |
@@ -0,0 +1,52 @@
1
+ // src/seo/index.ts
2
+ var setSeoData = ({ seo, route, locales = ["it", "en"] }) => {
3
+ if (!seo) return {};
4
+ const baseUrl = process.env.NEXT_PUBLIC_API_STORAGE_URL;
5
+ const frontUrl = process.env.NEXT_PUBLIC_BASE_URL;
6
+ const ogImg = seo.og_img?.original;
7
+ const ogUrl = ogImg?.compressed ? baseUrl + ogImg.compressed : frontUrl + "/images/og-image.jpg";
8
+ const languagesMap = {};
9
+ for (const loc of locales) {
10
+ if (route.slug?.[loc] !== void 0) {
11
+ languagesMap[loc] = `/${loc}/${route.slug[loc]}`;
12
+ }
13
+ }
14
+ const defaultLocale = locales[locales.length - 1];
15
+ if (route.slug?.[defaultLocale] !== void 0) {
16
+ languagesMap["x-default"] = `/${defaultLocale}/${route.slug[defaultLocale]}`;
17
+ }
18
+ return {
19
+ metadataBase: new URL(`${process.env.NEXT_PUBLIC_BASE_URL}`),
20
+ title: seo.meta_title || "",
21
+ description: seo.meta_description || "",
22
+ robots: {
23
+ index: seo.index === "index",
24
+ follow: seo.follow === "follow"
25
+ },
26
+ openGraph: {
27
+ title: seo.og_title || "",
28
+ description: seo.og_description || "",
29
+ url: seo.opengraphUrl || "",
30
+ siteName: seo.opengraphSiteName || "",
31
+ images: [
32
+ {
33
+ url: ogUrl,
34
+ width: ogImg?.width || 1200,
35
+ height: ogImg?.height || 630,
36
+ alt: ogImg?.alt || ""
37
+ }
38
+ ],
39
+ locale: route.locale,
40
+ type: seo.opengraphType || "website"
41
+ },
42
+ alternates: {
43
+ canonical: `${process.env.NEXT_PUBLIC_BASE_URL}/${route.locale}/${route.slug[route.locale]}`,
44
+ languages: languagesMap
45
+ }
46
+ };
47
+ };
48
+
49
+ export {
50
+ setSeoData
51
+ };
52
+ //# sourceMappingURL=chunk-3DP2A2OG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/seo/index.ts"],"sourcesContent":["export interface SeoDataOptions {\n seo: any;\n route: any;\n /**\n * Locale codes for hreflang alternates. Last entry becomes x-default.\n * Defaults to ['it', 'en'] when omitted.\n */\n locales?: string[];\n}\n\nexport const setSeoData = ({ seo, route, locales = ['it', 'en'] }: SeoDataOptions) => {\n if (!seo) return {};\n\n const baseUrl = process.env.NEXT_PUBLIC_API_STORAGE_URL;\n const frontUrl = process.env.NEXT_PUBLIC_BASE_URL;\n const ogImg = seo.og_img?.original;\n const ogUrl = ogImg?.compressed\n ? baseUrl + ogImg.compressed\n : frontUrl + '/images/og-image.jpg';\n\n const languagesMap: Record<string, string> = {};\n for (const loc of locales) {\n if (route.slug?.[loc] !== undefined) {\n languagesMap[loc] = `/${loc}/${route.slug[loc]}`;\n }\n }\n const defaultLocale = locales[locales.length - 1];\n if (route.slug?.[defaultLocale] !== undefined) {\n languagesMap['x-default'] = `/${defaultLocale}/${route.slug[defaultLocale]}`;\n }\n\n return {\n metadataBase: new URL(`${process.env.NEXT_PUBLIC_BASE_URL}`),\n title: seo.meta_title || '',\n description: seo.meta_description || '',\n robots: {\n index: seo.index === 'index',\n follow: seo.follow === 'follow',\n },\n openGraph: {\n title: seo.og_title || '',\n description: seo.og_description || '',\n url: seo.opengraphUrl || '',\n siteName: seo.opengraphSiteName || '',\n images: [\n {\n url: ogUrl,\n width: ogImg?.width || 1200,\n height: ogImg?.height || 630,\n alt: ogImg?.alt || '',\n },\n ],\n locale: route.locale,\n type: seo.opengraphType || 'website',\n },\n alternates: {\n canonical: `${process.env.NEXT_PUBLIC_BASE_URL}/${route.locale}/${route.slug[route.locale]}`,\n languages: languagesMap,\n },\n };\n};\n"],"mappings":";AAUO,IAAM,aAAa,CAAC,EAAE,KAAK,OAAO,UAAU,CAAC,MAAM,IAAI,EAAE,MAAsB;AACpF,MAAI,CAAC,IAAK,QAAO,CAAC;AAElB,QAAM,UAAU,QAAQ,IAAI;AAC5B,QAAM,WAAW,QAAQ,IAAI;AAC7B,QAAM,QAAQ,IAAI,QAAQ;AAC1B,QAAM,QAAQ,OAAO,aACjB,UAAU,MAAM,aAChB,WAAW;AAEf,QAAM,eAAuC,CAAC;AAC9C,aAAW,OAAO,SAAS;AACzB,QAAI,MAAM,OAAO,GAAG,MAAM,QAAW;AACnC,mBAAa,GAAG,IAAI,IAAI,GAAG,IAAI,MAAM,KAAK,GAAG,CAAC;AAAA,IAChD;AAAA,EACF;AACA,QAAM,gBAAgB,QAAQ,QAAQ,SAAS,CAAC;AAChD,MAAI,MAAM,OAAO,aAAa,MAAM,QAAW;AAC7C,iBAAa,WAAW,IAAI,IAAI,aAAa,IAAI,MAAM,KAAK,aAAa,CAAC;AAAA,EAC5E;AAEA,SAAO;AAAA,IACL,cAAc,IAAI,IAAI,GAAG,QAAQ,IAAI,oBAAoB,EAAE;AAAA,IAC3D,OAAO,IAAI,cAAc;AAAA,IACzB,aAAa,IAAI,oBAAoB;AAAA,IACrC,QAAQ;AAAA,MACN,OAAO,IAAI,UAAU;AAAA,MACrB,QAAQ,IAAI,WAAW;AAAA,IACzB;AAAA,IACA,WAAW;AAAA,MACT,OAAO,IAAI,YAAY;AAAA,MACvB,aAAa,IAAI,kBAAkB;AAAA,MACnC,KAAK,IAAI,gBAAgB;AAAA,MACzB,UAAU,IAAI,qBAAqB;AAAA,MACnC,QAAQ;AAAA,QACN;AAAA,UACE,KAAK;AAAA,UACL,OAAO,OAAO,SAAS;AAAA,UACvB,QAAQ,OAAO,UAAU;AAAA,UACzB,KAAK,OAAO,OAAO;AAAA,QACrB;AAAA,MACF;AAAA,MACA,QAAQ,MAAM;AAAA,MACd,MAAM,IAAI,iBAAiB;AAAA,IAC7B;AAAA,IACA,YAAY;AAAA,MACV,WAAW,GAAG,QAAQ,IAAI,oBAAoB,IAAI,MAAM,MAAM,IAAI,MAAM,KAAK,MAAM,MAAM,CAAC;AAAA,MAC1F,WAAW;AAAA,IACb;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,66 @@
1
+ // src/middleware/chain.ts
2
+ import { NextResponse } from "next/server";
3
+ function chain(functions = [], index = 0) {
4
+ const current = functions[index];
5
+ if (current) {
6
+ const next = chain(functions, index + 1);
7
+ return current(next);
8
+ }
9
+ return () => NextResponse.next();
10
+ }
11
+
12
+ // src/middleware/headermiddleware.ts
13
+ import { NextRequest } from "next/server";
14
+ var headermiddleware = (next) => {
15
+ return async (request, _next) => {
16
+ const url = new URL(request.url);
17
+ const params = new URLSearchParams(url.search);
18
+ const headers = new Headers(request.headers);
19
+ headers.set("x-current-path", request.nextUrl.pathname);
20
+ headers.set("x-server", "true");
21
+ headers.set("olmo-preview", params.has("olmopreview").toString());
22
+ return next(new NextRequest(request.url, { headers }), _next);
23
+ };
24
+ };
25
+
26
+ // src/middleware/redirectmiddleware.ts
27
+ import { NextResponse as NextResponse2 } from "next/server";
28
+ var redirectmiddleware = (next) => {
29
+ return async (request, _next) => {
30
+ if (request.headers.has("rsc")) {
31
+ return next(request, _next);
32
+ }
33
+ if (!process.env.NEXT_PUBLIC_OLMO_TOKEN || !process.env.NEXT_PUBLIC_API_URL || !process.env.NEXT_PUBLIC_BASE_URL) {
34
+ return next(request, _next);
35
+ }
36
+ const pathNameWithTrailingSlash = request.nextUrl.pathname;
37
+ const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/all/redirect`, {
38
+ method: "GET",
39
+ cache: "force-cache",
40
+ next: { tags: ["olmo", "redirect"] },
41
+ headers: { "front-token": process.env.NEXT_PUBLIC_OLMO_TOKEN }
42
+ });
43
+ const data = await response.json();
44
+ const redirects = data.map((e) => ({
45
+ source: e.source,
46
+ destination: e.destination,
47
+ permanent: e.permanent === "true"
48
+ }));
49
+ if (redirects.length > 0) {
50
+ const redirect = redirects.find((item) => item.source === pathNameWithTrailingSlash);
51
+ if (!redirect) {
52
+ return next(request, _next);
53
+ }
54
+ const newUrl = new URL(redirect.destination, process.env.NEXT_PUBLIC_BASE_URL).toString();
55
+ return NextResponse2.redirect(newUrl, { status: redirect.permanent ? 308 : 307 });
56
+ }
57
+ return next(request, _next);
58
+ };
59
+ };
60
+
61
+ export {
62
+ chain,
63
+ headermiddleware,
64
+ redirectmiddleware
65
+ };
66
+ //# sourceMappingURL=chunk-GQITFXCV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/middleware/chain.ts","../src/middleware/headermiddleware.ts","../src/middleware/redirectmiddleware.ts"],"sourcesContent":["import { NextResponse } from 'next/server';\nimport type { NextMiddleware } from 'next/server';\n\nexport type MiddlewareFactory = (middleware: NextMiddleware) => NextMiddleware;\n\nexport function chain(functions: MiddlewareFactory[] = [], index = 0): NextMiddleware {\n const current = functions[index];\n if (current) {\n const next = chain(functions, index + 1);\n return current(next);\n }\n return () => NextResponse.next();\n}\n","import { NextRequest } from 'next/server';\nimport type { NextFetchEvent } from 'next/server';\nimport type { MiddlewareFactory } from './chain.js';\n\nexport const headermiddleware: MiddlewareFactory = (next) => {\n return async (request: NextRequest, _next: NextFetchEvent) => {\n const url = new URL(request.url);\n const params = new URLSearchParams(url.search);\n\n const headers = new Headers(request.headers);\n headers.set('x-current-path', request.nextUrl.pathname);\n headers.set('x-server', 'true');\n headers.set('olmo-preview', params.has('olmopreview').toString());\n\n return next(new NextRequest(request.url, { headers }), _next);\n };\n};\n","import { NextResponse } from 'next/server';\nimport type { NextFetchEvent, NextRequest } from 'next/server';\nimport type { MiddlewareFactory } from './chain.js';\n\ntype NextFetchRequestInit = RequestInit & { next?: { tags?: string[]; revalidate?: number | false } };\n\nexport const redirectmiddleware: MiddlewareFactory = (next) => {\n return async (request: NextRequest, _next: NextFetchEvent) => {\n if (request.headers.has('rsc')) {\n return next(request, _next);\n }\n\n if (!process.env.NEXT_PUBLIC_OLMO_TOKEN || !process.env.NEXT_PUBLIC_API_URL || !process.env.NEXT_PUBLIC_BASE_URL) {\n return next(request, _next);\n }\n\n const pathNameWithTrailingSlash = request.nextUrl.pathname;\n\n const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/all/redirect`, {\n method: 'GET',\n cache: 'force-cache',\n next: { tags: ['olmo', 'redirect'] },\n headers: { 'front-token': process.env.NEXT_PUBLIC_OLMO_TOKEN },\n } as NextFetchRequestInit);\n\n const data = await response.json();\n\n const redirects = data.map((e: any) => ({\n source: e.source,\n destination: e.destination,\n permanent: e.permanent === 'true',\n }));\n\n if (redirects.length > 0) {\n const redirect = redirects.find((item: any) => item.source === pathNameWithTrailingSlash);\n\n if (!redirect) {\n return next(request, _next);\n }\n\n const newUrl = new URL(redirect.destination, process.env.NEXT_PUBLIC_BASE_URL).toString();\n return NextResponse.redirect(newUrl, { status: redirect.permanent ? 308 : 307 });\n }\n\n return next(request, _next);\n };\n};\n"],"mappings":";AAAA,SAAS,oBAAoB;AAKtB,SAAS,MAAM,YAAiC,CAAC,GAAG,QAAQ,GAAmB;AACpF,QAAM,UAAU,UAAU,KAAK;AAC/B,MAAI,SAAS;AACX,UAAM,OAAO,MAAM,WAAW,QAAQ,CAAC;AACvC,WAAO,QAAQ,IAAI;AAAA,EACrB;AACA,SAAO,MAAM,aAAa,KAAK;AACjC;;;ACZA,SAAS,mBAAmB;AAIrB,IAAM,mBAAsC,CAAC,SAAS;AAC3D,SAAO,OAAO,SAAsB,UAA0B;AAC5D,UAAM,MAAM,IAAI,IAAI,QAAQ,GAAG;AAC/B,UAAM,SAAS,IAAI,gBAAgB,IAAI,MAAM;AAE7C,UAAM,UAAU,IAAI,QAAQ,QAAQ,OAAO;AAC3C,YAAQ,IAAI,kBAAkB,QAAQ,QAAQ,QAAQ;AACtD,YAAQ,IAAI,YAAY,MAAM;AAC9B,YAAQ,IAAI,gBAAgB,OAAO,IAAI,aAAa,EAAE,SAAS,CAAC;AAEhE,WAAO,KAAK,IAAI,YAAY,QAAQ,KAAK,EAAE,QAAQ,CAAC,GAAG,KAAK;AAAA,EAC9D;AACF;;;AChBA,SAAS,gBAAAA,qBAAoB;AAMtB,IAAM,qBAAwC,CAAC,SAAS;AAC7D,SAAO,OAAO,SAAsB,UAA0B;AAC5D,QAAI,QAAQ,QAAQ,IAAI,KAAK,GAAG;AAC9B,aAAO,KAAK,SAAS,KAAK;AAAA,IAC5B;AAEA,QAAI,CAAC,QAAQ,IAAI,0BAA0B,CAAC,QAAQ,IAAI,uBAAuB,CAAC,QAAQ,IAAI,sBAAsB;AAChH,aAAO,KAAK,SAAS,KAAK;AAAA,IAC5B;AAEA,UAAM,4BAA4B,QAAQ,QAAQ;AAElD,UAAM,WAAW,MAAM,MAAM,GAAG,QAAQ,IAAI,mBAAmB,iBAAiB;AAAA,MAC9E,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,MAAM,EAAE,MAAM,CAAC,QAAQ,UAAU,EAAE;AAAA,MACnC,SAAS,EAAE,eAAe,QAAQ,IAAI,uBAAuB;AAAA,IAC/D,CAAyB;AAEzB,UAAM,OAAO,MAAM,SAAS,KAAK;AAEjC,UAAM,YAAY,KAAK,IAAI,CAAC,OAAY;AAAA,MACtC,QAAQ,EAAE;AAAA,MACV,aAAa,EAAE;AAAA,MACf,WAAW,EAAE,cAAc;AAAA,IAC7B,EAAE;AAEF,QAAI,UAAU,SAAS,GAAG;AACxB,YAAM,WAAW,UAAU,KAAK,CAAC,SAAc,KAAK,WAAW,yBAAyB;AAExF,UAAI,CAAC,UAAU;AACb,eAAO,KAAK,SAAS,KAAK;AAAA,MAC5B;AAEA,YAAM,SAAS,IAAI,IAAI,SAAS,aAAa,QAAQ,IAAI,oBAAoB,EAAE,SAAS;AACxF,aAAOA,cAAa,SAAS,QAAQ,EAAE,QAAQ,SAAS,YAAY,MAAM,IAAI,CAAC;AAAA,IACjF;AAEA,WAAO,KAAK,SAAS,KAAK;AAAA,EAC5B;AACF;","names":["NextResponse"]}
@@ -0,0 +1,79 @@
1
+ // src/client/index.ts
2
+ var API_BASE_URL = process.env.NEXT_PUBLIC_API_URL;
3
+ var API_TOKEN = process.env.NEXT_PUBLIC_OLMO_TOKEN;
4
+ var BASE_HEADERS = {
5
+ Accept: "application/json",
6
+ "Content-Type": "application/json",
7
+ "front-token": API_TOKEN
8
+ };
9
+ async function getting(lang, path, model = "") {
10
+ const isPreview = path.includes("?olmopreview");
11
+ try {
12
+ const response = await fetch(`${API_BASE_URL}${path}`, {
13
+ method: "GET",
14
+ headers: BASE_HEADERS,
15
+ cache: isPreview ? "no-cache" : "force-cache",
16
+ next: { tags: ["olmo", lang, path, model] }
17
+ });
18
+ if (!response.ok) {
19
+ console.error(`[olmo:get] ${response.status} ${response.statusText} \u2014 ${path}`);
20
+ return void 0;
21
+ }
22
+ return await response.json();
23
+ } catch (error) {
24
+ console.error(`[olmo:get] Network error \u2014 ${path}:`, error);
25
+ throw error;
26
+ }
27
+ }
28
+ async function posting(lang = "it", path, body) {
29
+ try {
30
+ const response = await fetch(`${API_BASE_URL}/${lang}/${path}`, {
31
+ method: "POST",
32
+ headers: BASE_HEADERS,
33
+ body: JSON.stringify(body),
34
+ cache: "force-cache",
35
+ next: { tags: ["olmo", `/${lang}/allmodel/${path}`] }
36
+ });
37
+ if (!response.ok) {
38
+ console.error(`[olmo:post] ${response.status} ${response.statusText} \u2014 /${lang}/${path}`);
39
+ throw new Error(`Olmo API error: ${response.status} ${response.statusText}`);
40
+ }
41
+ const data = await response.json();
42
+ if (data.errors) {
43
+ throw new Error(`Olmo API returned errors for /${lang}/${path}: ${JSON.stringify(data.errors)}`);
44
+ }
45
+ return data.response;
46
+ } catch (error) {
47
+ console.error(`[olmo:post] Error \u2014 /${lang}/${path}:`, error);
48
+ throw error;
49
+ }
50
+ }
51
+ async function filter(lang = "it", path, body) {
52
+ try {
53
+ const response = await fetch(`${API_BASE_URL}/${lang}/filters/${path}`, {
54
+ method: "POST",
55
+ headers: BASE_HEADERS,
56
+ body: JSON.stringify(body)
57
+ });
58
+ if (!response.ok) {
59
+ console.error(`[olmo:filter] ${response.status} ${response.statusText} \u2014 /${lang}/filters/${path}`);
60
+ throw new Error(`Olmo API error: ${response.status} ${response.statusText}`);
61
+ }
62
+ const data = await response.json();
63
+ if (data.errors) {
64
+ console.error(`[olmo:filter] API errors \u2014 /${lang}/filters/${path}:`, data.errors);
65
+ throw new Error(`Olmo API returned errors for /${lang}/filters/${path}: ${JSON.stringify(data.errors)}`);
66
+ }
67
+ return data;
68
+ } catch (error) {
69
+ console.error(`[olmo:filter] Error \u2014 /${lang}/filters/${path}:`, error);
70
+ throw error;
71
+ }
72
+ }
73
+
74
+ export {
75
+ getting,
76
+ posting,
77
+ filter
78
+ };
79
+ //# sourceMappingURL=chunk-JISDMUJ3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/client/index.ts"],"sourcesContent":["// Next.js extends RequestInit with a `next` property for cache tags / revalidation.\ntype NextRequestInit = RequestInit & {\n next?: { revalidate?: number | false; tags?: string[] };\n};\n\nconst API_BASE_URL = process.env.NEXT_PUBLIC_API_URL;\nconst API_TOKEN = process.env.NEXT_PUBLIC_OLMO_TOKEN as string;\n\nconst BASE_HEADERS: HeadersInit = {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'front-token': API_TOKEN,\n};\n\nexport async function getting<T = unknown>(\n lang: string,\n path: string,\n model = '',\n): Promise<T | undefined> {\n const isPreview = path.includes('?olmopreview');\n\n try {\n const response = await fetch(`${API_BASE_URL}${path}`, {\n method: 'GET',\n headers: BASE_HEADERS,\n cache: isPreview ? 'no-cache' : 'force-cache',\n next: { tags: ['olmo', lang, path, model] },\n } as NextRequestInit);\n\n if (!response.ok) {\n console.error(`[olmo:get] ${response.status} ${response.statusText} — ${path}`);\n return undefined;\n }\n\n return (await response.json()) as T;\n } catch (error) {\n console.error(`[olmo:get] Network error — ${path}:`, error);\n throw error;\n }\n}\n\nexport async function posting<T = unknown>(\n lang = 'it',\n path: string,\n body: object,\n): Promise<T> {\n try {\n const response = await fetch(`${API_BASE_URL}/${lang}/${path}`, {\n method: 'POST',\n headers: BASE_HEADERS,\n body: JSON.stringify(body),\n cache: 'force-cache',\n next: { tags: ['olmo', `/${lang}/allmodel/${path}`] },\n } as NextRequestInit);\n\n if (!response.ok) {\n console.error(`[olmo:post] ${response.status} ${response.statusText} — /${lang}/${path}`);\n throw new Error(`Olmo API error: ${response.status} ${response.statusText}`);\n }\n\n const data = await response.json();\n\n if (data.errors) {\n throw new Error(`Olmo API returned errors for /${lang}/${path}: ${JSON.stringify(data.errors)}`);\n }\n\n return data.response as T;\n } catch (error) {\n console.error(`[olmo:post] Error — /${lang}/${path}:`, error);\n throw error;\n }\n}\n\nexport async function filter<T = unknown>(\n lang = 'it',\n path: string,\n body: object,\n): Promise<T> {\n try {\n const response = await fetch(`${API_BASE_URL}/${lang}/filters/${path}`, {\n method: 'POST',\n headers: BASE_HEADERS,\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n console.error(`[olmo:filter] ${response.status} ${response.statusText} — /${lang}/filters/${path}`);\n throw new Error(`Olmo API error: ${response.status} ${response.statusText}`);\n }\n\n const data = await response.json();\n\n if (data.errors) {\n console.error(`[olmo:filter] API errors — /${lang}/filters/${path}:`, data.errors);\n throw new Error(`Olmo API returned errors for /${lang}/filters/${path}: ${JSON.stringify(data.errors)}`);\n }\n\n return data as T;\n } catch (error) {\n console.error(`[olmo:filter] Error — /${lang}/filters/${path}:`, error);\n throw error;\n }\n}\n"],"mappings":";AAKA,IAAM,eAAe,QAAQ,IAAI;AACjC,IAAM,YAAY,QAAQ,IAAI;AAE9B,IAAM,eAA4B;AAAA,EAChC,QAAQ;AAAA,EACR,gBAAgB;AAAA,EAChB,eAAe;AACjB;AAEA,eAAsB,QACpB,MACA,MACA,QAAQ,IACgB;AACxB,QAAM,YAAY,KAAK,SAAS,cAAc;AAE9C,MAAI;AACF,UAAM,WAAW,MAAM,MAAM,GAAG,YAAY,GAAG,IAAI,IAAI;AAAA,MACrD,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,OAAO,YAAY,aAAa;AAAA,MAChC,MAAM,EAAE,MAAM,CAAC,QAAQ,MAAM,MAAM,KAAK,EAAE;AAAA,IAC5C,CAAoB;AAEpB,QAAI,CAAC,SAAS,IAAI;AAChB,cAAQ,MAAM,cAAc,SAAS,MAAM,IAAI,SAAS,UAAU,WAAM,IAAI,EAAE;AAC9E,aAAO;AAAA,IACT;AAEA,WAAQ,MAAM,SAAS,KAAK;AAAA,EAC9B,SAAS,OAAO;AACd,YAAQ,MAAM,mCAA8B,IAAI,KAAK,KAAK;AAC1D,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,QACpB,OAAO,MACP,MACA,MACY;AACZ,MAAI;AACF,UAAM,WAAW,MAAM,MAAM,GAAG,YAAY,IAAI,IAAI,IAAI,IAAI,IAAI;AAAA,MAC9D,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,MAAM,KAAK,UAAU,IAAI;AAAA,MACzB,OAAO;AAAA,MACP,MAAM,EAAE,MAAM,CAAC,QAAQ,IAAI,IAAI,aAAa,IAAI,EAAE,EAAE;AAAA,IACtD,CAAoB;AAEpB,QAAI,CAAC,SAAS,IAAI;AAChB,cAAQ,MAAM,eAAe,SAAS,MAAM,IAAI,SAAS,UAAU,YAAO,IAAI,IAAI,IAAI,EAAE;AACxF,YAAM,IAAI,MAAM,mBAAmB,SAAS,MAAM,IAAI,SAAS,UAAU,EAAE;AAAA,IAC7E;AAEA,UAAM,OAAO,MAAM,SAAS,KAAK;AAEjC,QAAI,KAAK,QAAQ;AACf,YAAM,IAAI,MAAM,iCAAiC,IAAI,IAAI,IAAI,KAAK,KAAK,UAAU,KAAK,MAAM,CAAC,EAAE;AAAA,IACjG;AAEA,WAAO,KAAK;AAAA,EACd,SAAS,OAAO;AACd,YAAQ,MAAM,6BAAwB,IAAI,IAAI,IAAI,KAAK,KAAK;AAC5D,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,OACpB,OAAO,MACP,MACA,MACY;AACZ,MAAI;AACF,UAAM,WAAW,MAAM,MAAM,GAAG,YAAY,IAAI,IAAI,YAAY,IAAI,IAAI;AAAA,MACtE,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,MAAM,KAAK,UAAU,IAAI;AAAA,IAC3B,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,cAAQ,MAAM,iBAAiB,SAAS,MAAM,IAAI,SAAS,UAAU,YAAO,IAAI,YAAY,IAAI,EAAE;AAClG,YAAM,IAAI,MAAM,mBAAmB,SAAS,MAAM,IAAI,SAAS,UAAU,EAAE;AAAA,IAC7E;AAEA,UAAM,OAAO,MAAM,SAAS,KAAK;AAEjC,QAAI,KAAK,QAAQ;AACf,cAAQ,MAAM,oCAA+B,IAAI,YAAY,IAAI,KAAK,KAAK,MAAM;AACjF,YAAM,IAAI,MAAM,iCAAiC,IAAI,YAAY,IAAI,KAAK,KAAK,UAAU,KAAK,MAAM,CAAC,EAAE;AAAA,IACzG;AAEA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,YAAQ,MAAM,+BAA0B,IAAI,YAAY,IAAI,KAAK,KAAK;AACtE,UAAM;AAAA,EACR;AACF;","names":[]}
@@ -0,0 +1,61 @@
1
+ // src/jsonld/index.ts
2
+ var BASE_URL = process.env.NEXT_PUBLIC_BASE_URL;
3
+ var STORAGE_URL = process.env.NEXT_PUBLIC_API_STORAGE_URL;
4
+ var SITE_NAME = process.env.NEXT_PUBLIC_SITE_NAME ?? "Website";
5
+ var buildBreadcrumb = (items) => ({
6
+ "@context": "https://schema.org",
7
+ "@type": "BreadcrumbList",
8
+ itemListElement: items.map((item, index) => ({
9
+ "@type": "ListItem",
10
+ position: index + 1,
11
+ name: item.name,
12
+ item: item.url
13
+ }))
14
+ });
15
+ var buildItemList = (items, sectionUrl) => ({
16
+ "@context": "https://schema.org",
17
+ "@type": "ItemList",
18
+ itemListElement: items.map((item, index) => ({
19
+ "@type": "ListItem",
20
+ position: index + 1,
21
+ name: item.title_txt_content || item.name_txt_general,
22
+ url: `${sectionUrl}${item.slug_txt_general}/`
23
+ }))
24
+ });
25
+ var buildArticle = (page, pathname, articleType = "Article", publisherName) => {
26
+ const name = publisherName ?? SITE_NAME;
27
+ const pageUrl = `${BASE_URL}${pathname.endsWith("/") ? pathname : pathname + "/"}`;
28
+ const imageUrl = (page.primary ?? page.cover)?.original?.compressed ? `${STORAGE_URL}${(page.primary ?? page.cover).original.compressed}` : void 0;
29
+ const description = page.subtitle ? page.subtitle.replace(/<[^>]*>/g, "").trim() : void 0;
30
+ const publisher = {
31
+ "@type": "Organization",
32
+ name,
33
+ url: BASE_URL,
34
+ logo: { "@type": "ImageObject", url: `${BASE_URL}/images/logo/logo.png` }
35
+ };
36
+ return {
37
+ "@context": "https://schema.org",
38
+ "@type": articleType,
39
+ headline: page.title,
40
+ ...description && { description },
41
+ ...imageUrl && { image: imageUrl },
42
+ url: pageUrl,
43
+ author: publisher,
44
+ publisher,
45
+ ...page.lastmod && { datePublished: page.lastmod, dateModified: page.lastmod }
46
+ };
47
+ };
48
+ var buildWebSite = (locale, siteName) => ({
49
+ "@context": "https://schema.org",
50
+ "@type": "WebSite",
51
+ name: siteName ?? SITE_NAME,
52
+ url: `${BASE_URL}/${locale}/`
53
+ });
54
+
55
+ export {
56
+ buildBreadcrumb,
57
+ buildItemList,
58
+ buildArticle,
59
+ buildWebSite
60
+ };
61
+ //# sourceMappingURL=chunk-RG54JLA2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/jsonld/index.ts"],"sourcesContent":["const BASE_URL = process.env.NEXT_PUBLIC_BASE_URL!;\nconst STORAGE_URL = process.env.NEXT_PUBLIC_API_STORAGE_URL!;\nconst SITE_NAME = process.env.NEXT_PUBLIC_SITE_NAME ?? 'Website';\n\ntype BreadcrumbItem = { name: string; url: string };\n\nexport const buildBreadcrumb = (items: BreadcrumbItem[]) => ({\n '@context': 'https://schema.org',\n '@type': 'BreadcrumbList',\n itemListElement: items.map((item, index) => ({\n '@type': 'ListItem',\n position: index + 1,\n name: item.name,\n item: item.url,\n })),\n});\n\nexport const buildItemList = (items: any[], sectionUrl: string) => ({\n '@context': 'https://schema.org',\n '@type': 'ItemList',\n itemListElement: items.map((item, index) => ({\n '@type': 'ListItem',\n position: index + 1,\n name: item.title_txt_content || item.name_txt_general,\n url: `${sectionUrl}${item.slug_txt_general}/`,\n })),\n});\n\nexport const buildArticle = (\n page: any,\n pathname: string,\n articleType: 'Article' | 'NewsArticle' = 'Article',\n publisherName?: string,\n) => {\n const name = publisherName ?? SITE_NAME;\n const pageUrl = `${BASE_URL}${pathname.endsWith('/') ? pathname : pathname + '/'}`;\n const imageUrl = (page.primary ?? page.cover)?.original?.compressed\n ? `${STORAGE_URL}${(page.primary ?? page.cover).original.compressed}`\n : undefined;\n const description = page.subtitle\n ? page.subtitle.replace(/<[^>]*>/g, '').trim()\n : undefined;\n\n const publisher = {\n '@type': 'Organization',\n name,\n url: BASE_URL,\n logo: { '@type': 'ImageObject', url: `${BASE_URL}/images/logo/logo.png` },\n };\n\n return {\n '@context': 'https://schema.org',\n '@type': articleType,\n headline: page.title,\n ...(description && { description }),\n ...(imageUrl && { image: imageUrl }),\n url: pageUrl,\n author: publisher,\n publisher,\n ...(page.lastmod && { datePublished: page.lastmod, dateModified: page.lastmod }),\n };\n};\n\nexport const buildWebSite = (locale: string, siteName?: string) => ({\n '@context': 'https://schema.org',\n '@type': 'WebSite',\n name: siteName ?? SITE_NAME,\n url: `${BASE_URL}/${locale}/`,\n});\n"],"mappings":";AAAA,IAAM,WAAW,QAAQ,IAAI;AAC7B,IAAM,cAAc,QAAQ,IAAI;AAChC,IAAM,YAAY,QAAQ,IAAI,yBAAyB;AAIhD,IAAM,kBAAkB,CAAC,WAA6B;AAAA,EAC3D,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,iBAAiB,MAAM,IAAI,CAAC,MAAM,WAAW;AAAA,IAC3C,SAAS;AAAA,IACT,UAAU,QAAQ;AAAA,IAClB,MAAM,KAAK;AAAA,IACX,MAAM,KAAK;AAAA,EACb,EAAE;AACJ;AAEO,IAAM,gBAAgB,CAAC,OAAc,gBAAwB;AAAA,EAClE,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,iBAAiB,MAAM,IAAI,CAAC,MAAM,WAAW;AAAA,IAC3C,SAAS;AAAA,IACT,UAAU,QAAQ;AAAA,IAClB,MAAM,KAAK,qBAAqB,KAAK;AAAA,IACrC,KAAK,GAAG,UAAU,GAAG,KAAK,gBAAgB;AAAA,EAC5C,EAAE;AACJ;AAEO,IAAM,eAAe,CAC1B,MACA,UACA,cAAyC,WACzC,kBACG;AACH,QAAM,OAAO,iBAAiB;AAC9B,QAAM,UAAU,GAAG,QAAQ,GAAG,SAAS,SAAS,GAAG,IAAI,WAAW,WAAW,GAAG;AAChF,QAAM,YAAY,KAAK,WAAW,KAAK,QAAQ,UAAU,aACrD,GAAG,WAAW,IAAI,KAAK,WAAW,KAAK,OAAO,SAAS,UAAU,KACjE;AACJ,QAAM,cAAc,KAAK,WACrB,KAAK,SAAS,QAAQ,YAAY,EAAE,EAAE,KAAK,IAC3C;AAEJ,QAAM,YAAY;AAAA,IAChB,SAAS;AAAA,IACT;AAAA,IACA,KAAK;AAAA,IACL,MAAM,EAAE,SAAS,eAAe,KAAK,GAAG,QAAQ,wBAAwB;AAAA,EAC1E;AAEA,SAAO;AAAA,IACL,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,UAAU,KAAK;AAAA,IACf,GAAI,eAAe,EAAE,YAAY;AAAA,IACjC,GAAI,YAAY,EAAE,OAAO,SAAS;AAAA,IAClC,KAAK;AAAA,IACL,QAAQ;AAAA,IACR;AAAA,IACA,GAAI,KAAK,WAAW,EAAE,eAAe,KAAK,SAAS,cAAc,KAAK,QAAQ;AAAA,EAChF;AACF;AAEO,IAAM,eAAe,CAAC,QAAgB,cAAuB;AAAA,EAClE,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,MAAM,YAAY;AAAA,EAClB,KAAK,GAAG,QAAQ,IAAI,MAAM;AAC5B;","names":[]}