@olmocms/front 0.1.1 → 0.1.5

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 CHANGED
@@ -9,8 +9,7 @@ Shared utilities, React components, SEO helpers, middleware, and CLI scaffold to
9
9
  - [Package entries](#package-entries)
10
10
  - [Installation](#installation)
11
11
  - [Local development (watch mode)](#local-development-watch-mode)
12
- - [Publishing to npm](#publishing-to-npm)
13
- - [Versioning](#versioning)
12
+ - [Releasing a new version](#releasing-a-new-version)
14
13
  - [CLI — olmo-front](#cli--olmo-front)
15
14
  - [Entry point reference](#entry-point-reference)
16
15
 
@@ -91,71 +90,58 @@ Then run `npm install`.
91
90
 
92
91
  ---
93
92
 
94
- ## Publishing to npm
93
+ ## Releasing a new version
95
94
 
96
- ### Prerequisites
95
+ Releases are automated by GitLab CI: pushing a `vX.Y.Z` git tag triggers `npm publish` to the public npm registry. You do **not** run `npm publish` manually for normal releases.
97
96
 
98
- - npm account with access to the `@olmocms` org
99
- - npm auth token (Publish scope) stored in `.npmrc`
97
+ ### Day-to-day release flow
100
98
 
101
- ### Step 1 Set up `.npmrc`
99
+ From a clean working tree on `main`:
102
100
 
103
101
  ```bash
104
- cp .npmrc.example .npmrc
102
+ npm version patch # or minor / major — bumps package.json AND creates a vX.Y.Z git tag
103
+ git push origin main --follow-tags
105
104
  ```
106
105
 
107
- Replace `YOUR_NPM_TOKEN` with a token from **https://www.npmjs.com/settings/\<username\>/tokens**.
106
+ That's the whole release. GitLab CI then:
108
107
 
109
- ### Step 2 Build
108
+ 1. Runs `typecheck` and `build` on every push (see `.gitlab-ci.yml`).
109
+ 2. On a tag matching `^v\d+\.\d+\.\d+$`, runs the `publish` job, which writes `NPM_TOKEN` into `~/.npmrc` and runs `npm publish`. `publishConfig.access: "public"` in `package.json` makes it a public scoped publish.
110
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
- ```
111
+ Watch the pipeline at **GitLab → CI/CD → Pipelines**. When green, verify on **https://www.npmjs.com/package/@olmocms/front**.
126
112
 
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
113
+ ### Version bump rules
136
114
 
137
115
  Follow semantic versioning (`MAJOR.MINOR.PATCH`):
138
116
 
139
- | Change type | Version bump | Example |
117
+ | Change | Bump | Example |
140
118
  |---|---|---|
141
119
  | Breaking API change | MAJOR | `0.x.x` → `1.0.0` |
142
120
  | New entry point or new export | MINOR | `0.1.0` → `0.2.0` |
143
121
  | Bug fix, internal refactor | PATCH | `0.1.0` → `0.1.1` |
144
122
 
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
- ```
123
+ npm rejects re-publishing an existing version, so always bump first.
124
+
125
+ ### One-time setup (reference already done)
126
+
127
+ Kept here so the wiring is recoverable if the project is ever cloned fresh or the token rotates:
150
128
 
151
- Then:
129
+ - **npm.js org** — the `@olmocms` organization owns the scope on npmjs.com.
130
+ - **npm automation token** — generated under *Account → Access Tokens → Generate New Token → Granular Access Token* (or a classic *Automation* token), scoped to publish `@olmocms/*`. Automation tokens bypass 2FA, which CI requires.
131
+ - **GitLab CI/CD variable** — token stored as `NPM_TOKEN` under *Settings → CI/CD → Variables*, marked **Masked** and **Protected**.
132
+ - **GitLab protected tag** — `v*` added under *Settings → Repository → Protected tags*, so only protected refs can read `NPM_TOKEN`.
133
+ - **`.gitlab-ci.yml`** — defines `typecheck`, `build`, and the tag-gated `publish` job.
134
+
135
+ ### Manual publish (fallback only)
136
+
137
+ Only needed for the very first publish of a new scope or if CI is broken:
152
138
 
153
139
  ```bash
154
- npm run build && npm publish
140
+ npm login
141
+ npm run build
142
+ npm publish
155
143
  ```
156
144
 
157
- npm does not allow overwriting an existing version — always increment before publishing.
158
-
159
145
  ---
160
146
 
161
147
  ## CLI — olmo-front
@@ -0,0 +1,107 @@
1
+ "use server";
2
+ "use strict";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // src/auth/action.ts
22
+ var action_exports = {};
23
+ __export(action_exports, {
24
+ stageLoginAction: () => stageLoginAction
25
+ });
26
+ module.exports = __toCommonJS(action_exports);
27
+ var import_headers = require("next/headers");
28
+ var import_navigation = require("next/navigation");
29
+
30
+ // src/auth/stage.ts
31
+ var COOKIE_NAME = "olmo_stage_auth";
32
+ var DEFAULT_SESSION_DAYS = 7;
33
+ function readStageEnv() {
34
+ const username = process.env.OLMO_STAGE_USERNAME;
35
+ const password = process.env.OLMO_STAGE_PASSWORD;
36
+ const secret = process.env.OLMO_STAGE_SECRET;
37
+ if (!username || !password || !secret) return null;
38
+ const days = Number(process.env.OLMO_STAGE_SESSION_DAYS);
39
+ return {
40
+ username,
41
+ password,
42
+ secret,
43
+ sessionDays: Number.isFinite(days) && days > 0 ? days : DEFAULT_SESSION_DAYS
44
+ };
45
+ }
46
+ function getStageCookieName() {
47
+ return COOKIE_NAME;
48
+ }
49
+ function toBase64Url(bytes) {
50
+ const arr = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);
51
+ let str = "";
52
+ for (let i = 0; i < arr.length; i++) str += String.fromCharCode(arr[i]);
53
+ return btoa(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
54
+ }
55
+ async function importKey(secret) {
56
+ return crypto.subtle.importKey(
57
+ "raw",
58
+ new TextEncoder().encode(secret),
59
+ { name: "HMAC", hash: "SHA-256" },
60
+ false,
61
+ ["sign", "verify"]
62
+ );
63
+ }
64
+ async function signSession(payload, secret) {
65
+ const body = toBase64Url(new TextEncoder().encode(JSON.stringify(payload)));
66
+ const key = await importKey(secret);
67
+ const sig = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(body));
68
+ return `${body}.${toBase64Url(sig)}`;
69
+ }
70
+ function verifyCredentials(env, username, password) {
71
+ if (typeof username !== "string" || typeof password !== "string") return false;
72
+ return username === env.username && password === env.password;
73
+ }
74
+
75
+ // src/auth/action.ts
76
+ function safeRedirectTarget(raw) {
77
+ if (typeof raw !== "string" || raw.length === 0) return "/";
78
+ if (!raw.startsWith("/") || raw.startsWith("//")) return "/";
79
+ return raw;
80
+ }
81
+ async function stageLoginAction(_prev, formData) {
82
+ const env = readStageEnv();
83
+ if (!env) return { error: "missing_config" };
84
+ const username = formData.get("username");
85
+ const password = formData.get("password");
86
+ if (!verifyCredentials(env, username, password)) {
87
+ return { error: "invalid_credentials" };
88
+ }
89
+ const exp = Date.now() + env.sessionDays * 24 * 60 * 60 * 1e3;
90
+ const token = await signSession({ u: env.username, exp }, env.secret);
91
+ const store = await (0, import_headers.cookies)();
92
+ store.set(getStageCookieName(), token, {
93
+ httpOnly: true,
94
+ // secure must be false on HTTP dev (next dev on localhost) so the browser stores
95
+ // the cookie. In production builds (next start / Vercel) this becomes true.
96
+ secure: process.env.NODE_ENV === "production",
97
+ sameSite: "lax",
98
+ path: "/",
99
+ expires: new Date(exp)
100
+ });
101
+ (0, import_navigation.redirect)(safeRedirectTarget(formData.get("from")));
102
+ }
103
+ // Annotate the CommonJS export names for ESM import in node:
104
+ 0 && (module.exports = {
105
+ stageLoginAction
106
+ });
107
+ //# sourceMappingURL=action.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/auth/action.ts","../../src/auth/stage.ts"],"sourcesContent":["// 'use server' is injected by the tsup banner — keep this file directive-free\n// so the bundled output has exactly one directive at the top.\nimport { cookies } from 'next/headers';\nimport { redirect } from 'next/navigation';\nimport { getStageCookieName, readStageEnv, signSession, verifyCredentials } from './stage.js';\n\nexport type StageLoginState = { error?: 'missing_config' | 'invalid_credentials' | null };\n\nfunction safeRedirectTarget(raw: unknown): string {\n if (typeof raw !== 'string' || raw.length === 0) return '/';\n if (!raw.startsWith('/') || raw.startsWith('//')) return '/';\n return raw;\n}\n\nexport async function stageLoginAction(_prev: StageLoginState, formData: FormData): Promise<StageLoginState> {\n const env = readStageEnv();\n if (!env) return { error: 'missing_config' };\n\n const username = formData.get('username');\n const password = formData.get('password');\n if (!verifyCredentials(env, username, password)) {\n return { error: 'invalid_credentials' };\n }\n\n const exp = Date.now() + env.sessionDays * 24 * 60 * 60 * 1000;\n const token = await signSession({ u: env.username, exp }, env.secret);\n\n const store = await cookies();\n store.set(getStageCookieName(), token, {\n httpOnly: true,\n // secure must be false on HTTP dev (next dev on localhost) so the browser stores\n // the cookie. In production builds (next start / Vercel) this becomes true.\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n path: '/',\n expires: new Date(exp),\n });\n\n redirect(safeRedirectTarget(formData.get('from')));\n}\n","// Internal helpers for the stage-environment auth gate.\n// Edge-runtime safe (uses Web Crypto, no Node APIs).\n\nconst COOKIE_NAME = 'olmo_stage_auth';\nconst DEFAULT_SESSION_DAYS = 7;\n\nexport type StagePayload = { u: string; exp: number };\n\nexport type StageEnv = {\n username: string;\n password: string;\n secret: string;\n sessionDays: number;\n};\n\nexport function readStageEnv(): StageEnv | null {\n const username = process.env.OLMO_STAGE_USERNAME;\n const password = process.env.OLMO_STAGE_PASSWORD;\n const secret = process.env.OLMO_STAGE_SECRET;\n if (!username || !password || !secret) return null;\n const days = Number(process.env.OLMO_STAGE_SESSION_DAYS);\n return {\n username,\n password,\n secret,\n sessionDays: Number.isFinite(days) && days > 0 ? days : DEFAULT_SESSION_DAYS,\n };\n}\n\nexport function getStageCookieName(): string {\n return COOKIE_NAME;\n}\n\nfunction toBase64Url(bytes: ArrayBuffer | Uint8Array): string {\n const arr = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);\n let str = '';\n for (let i = 0; i < arr.length; i++) str += String.fromCharCode(arr[i]);\n return btoa(str).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\nfunction fromBase64Url(input: string): Uint8Array {\n const pad = input.length % 4 === 0 ? '' : '='.repeat(4 - (input.length % 4));\n const b64 = input.replace(/-/g, '+').replace(/_/g, '/') + pad;\n const bin = atob(b64);\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\nasync function importKey(secret: string): Promise<CryptoKey> {\n return crypto.subtle.importKey(\n 'raw',\n new TextEncoder().encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign', 'verify'],\n );\n}\n\nexport async function signSession(payload: StagePayload, secret: string): Promise<string> {\n const body = toBase64Url(new TextEncoder().encode(JSON.stringify(payload)));\n const key = await importKey(secret);\n const sig = await crypto.subtle.sign('HMAC', key, new TextEncoder().encode(body));\n return `${body}.${toBase64Url(sig)}`;\n}\n\nexport async function verifySession(token: string | undefined, secret: string): Promise<StagePayload | null> {\n if (!token || typeof token !== 'string' || token.indexOf('.') === -1) return null;\n const [body, sig] = token.split('.');\n if (!body || !sig) return null;\n let key: CryptoKey;\n try {\n key = await importKey(secret);\n } catch {\n return null;\n }\n let valid = false;\n try {\n valid = await crypto.subtle.verify('HMAC', key, fromBase64Url(sig) as BufferSource, new TextEncoder().encode(body));\n } catch {\n return null;\n }\n if (!valid) return null;\n let payload: StagePayload;\n try {\n payload = JSON.parse(new TextDecoder().decode(fromBase64Url(body)));\n } catch {\n return null;\n }\n if (!payload || typeof payload.exp !== 'number' || payload.exp < Date.now()) return null;\n return payload;\n}\n\nexport function verifyCredentials(env: StageEnv, username: unknown, password: unknown): boolean {\n if (typeof username !== 'string' || typeof password !== 'string') return false;\n return username === env.username && password === env.password;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,qBAAwB;AACxB,wBAAyB;;;ACAzB,IAAM,cAAc;AACpB,IAAM,uBAAuB;AAWtB,SAAS,eAAgC;AAC9C,QAAM,WAAW,QAAQ,IAAI;AAC7B,QAAM,WAAW,QAAQ,IAAI;AAC7B,QAAM,SAAS,QAAQ,IAAI;AAC3B,MAAI,CAAC,YAAY,CAAC,YAAY,CAAC,OAAQ,QAAO;AAC9C,QAAM,OAAO,OAAO,QAAQ,IAAI,uBAAuB;AACvD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa,OAAO,SAAS,IAAI,KAAK,OAAO,IAAI,OAAO;AAAA,EAC1D;AACF;AAEO,SAAS,qBAA6B;AAC3C,SAAO;AACT;AAEA,SAAS,YAAY,OAAyC;AAC5D,QAAM,MAAM,iBAAiB,aAAa,QAAQ,IAAI,WAAW,KAAK;AACtE,MAAI,MAAM;AACV,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,IAAK,QAAO,OAAO,aAAa,IAAI,CAAC,CAAC;AACtE,SAAO,KAAK,GAAG,EAAE,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,EAAE;AAC5E;AAWA,eAAe,UAAU,QAAoC;AAC3D,SAAO,OAAO,OAAO;AAAA,IACnB;AAAA,IACA,IAAI,YAAY,EAAE,OAAO,MAAM;AAAA,IAC/B,EAAE,MAAM,QAAQ,MAAM,UAAU;AAAA,IAChC;AAAA,IACA,CAAC,QAAQ,QAAQ;AAAA,EACnB;AACF;AAEA,eAAsB,YAAY,SAAuB,QAAiC;AACxF,QAAM,OAAO,YAAY,IAAI,YAAY,EAAE,OAAO,KAAK,UAAU,OAAO,CAAC,CAAC;AAC1E,QAAM,MAAM,MAAM,UAAU,MAAM;AAClC,QAAM,MAAM,MAAM,OAAO,OAAO,KAAK,QAAQ,KAAK,IAAI,YAAY,EAAE,OAAO,IAAI,CAAC;AAChF,SAAO,GAAG,IAAI,IAAI,YAAY,GAAG,CAAC;AACpC;AA6BO,SAAS,kBAAkB,KAAe,UAAmB,UAA4B;AAC9F,MAAI,OAAO,aAAa,YAAY,OAAO,aAAa,SAAU,QAAO;AACzE,SAAO,aAAa,IAAI,YAAY,aAAa,IAAI;AACvD;;;ADxFA,SAAS,mBAAmB,KAAsB;AAChD,MAAI,OAAO,QAAQ,YAAY,IAAI,WAAW,EAAG,QAAO;AACxD,MAAI,CAAC,IAAI,WAAW,GAAG,KAAK,IAAI,WAAW,IAAI,EAAG,QAAO;AACzD,SAAO;AACT;AAEA,eAAsB,iBAAiB,OAAwB,UAA8C;AAC3G,QAAM,MAAM,aAAa;AACzB,MAAI,CAAC,IAAK,QAAO,EAAE,OAAO,iBAAiB;AAE3C,QAAM,WAAW,SAAS,IAAI,UAAU;AACxC,QAAM,WAAW,SAAS,IAAI,UAAU;AACxC,MAAI,CAAC,kBAAkB,KAAK,UAAU,QAAQ,GAAG;AAC/C,WAAO,EAAE,OAAO,sBAAsB;AAAA,EACxC;AAEA,QAAM,MAAM,KAAK,IAAI,IAAI,IAAI,cAAc,KAAK,KAAK,KAAK;AAC1D,QAAM,QAAQ,MAAM,YAAY,EAAE,GAAG,IAAI,UAAU,IAAI,GAAG,IAAI,MAAM;AAEpE,QAAM,QAAQ,UAAM,wBAAQ;AAC5B,QAAM,IAAI,mBAAmB,GAAG,OAAO;AAAA,IACrC,UAAU;AAAA;AAAA;AAAA,IAGV,QAAQ,QAAQ,IAAI,aAAa;AAAA,IACjC,UAAU;AAAA,IACV,MAAM;AAAA,IACN,SAAS,IAAI,KAAK,GAAG;AAAA,EACvB,CAAC;AAED,kCAAS,mBAAmB,SAAS,IAAI,MAAM,CAAC,CAAC;AACnD;","names":[]}
@@ -0,0 +1,6 @@
1
+ type StageLoginState = {
2
+ error?: 'missing_config' | 'invalid_credentials' | null;
3
+ };
4
+ declare function stageLoginAction(_prev: StageLoginState, formData: FormData): Promise<StageLoginState>;
5
+
6
+ export { type StageLoginState, stageLoginAction };
@@ -0,0 +1,6 @@
1
+ type StageLoginState = {
2
+ error?: 'missing_config' | 'invalid_credentials' | null;
3
+ };
4
+ declare function stageLoginAction(_prev: StageLoginState, formData: FormData): Promise<StageLoginState>;
5
+
6
+ export { type StageLoginState, stageLoginAction };
@@ -0,0 +1,83 @@
1
+ "use server";
2
+
3
+ // src/auth/action.ts
4
+ import { cookies } from "next/headers";
5
+ import { redirect } from "next/navigation";
6
+
7
+ // src/auth/stage.ts
8
+ var COOKIE_NAME = "olmo_stage_auth";
9
+ var DEFAULT_SESSION_DAYS = 7;
10
+ function readStageEnv() {
11
+ const username = process.env.OLMO_STAGE_USERNAME;
12
+ const password = process.env.OLMO_STAGE_PASSWORD;
13
+ const secret = process.env.OLMO_STAGE_SECRET;
14
+ if (!username || !password || !secret) return null;
15
+ const days = Number(process.env.OLMO_STAGE_SESSION_DAYS);
16
+ return {
17
+ username,
18
+ password,
19
+ secret,
20
+ sessionDays: Number.isFinite(days) && days > 0 ? days : DEFAULT_SESSION_DAYS
21
+ };
22
+ }
23
+ function getStageCookieName() {
24
+ return COOKIE_NAME;
25
+ }
26
+ function toBase64Url(bytes) {
27
+ const arr = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);
28
+ let str = "";
29
+ for (let i = 0; i < arr.length; i++) str += String.fromCharCode(arr[i]);
30
+ return btoa(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
31
+ }
32
+ async function importKey(secret) {
33
+ return crypto.subtle.importKey(
34
+ "raw",
35
+ new TextEncoder().encode(secret),
36
+ { name: "HMAC", hash: "SHA-256" },
37
+ false,
38
+ ["sign", "verify"]
39
+ );
40
+ }
41
+ async function signSession(payload, secret) {
42
+ const body = toBase64Url(new TextEncoder().encode(JSON.stringify(payload)));
43
+ const key = await importKey(secret);
44
+ const sig = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(body));
45
+ return `${body}.${toBase64Url(sig)}`;
46
+ }
47
+ function verifyCredentials(env, username, password) {
48
+ if (typeof username !== "string" || typeof password !== "string") return false;
49
+ return username === env.username && password === env.password;
50
+ }
51
+
52
+ // src/auth/action.ts
53
+ function safeRedirectTarget(raw) {
54
+ if (typeof raw !== "string" || raw.length === 0) return "/";
55
+ if (!raw.startsWith("/") || raw.startsWith("//")) return "/";
56
+ return raw;
57
+ }
58
+ async function stageLoginAction(_prev, formData) {
59
+ const env = readStageEnv();
60
+ if (!env) return { error: "missing_config" };
61
+ const username = formData.get("username");
62
+ const password = formData.get("password");
63
+ if (!verifyCredentials(env, username, password)) {
64
+ return { error: "invalid_credentials" };
65
+ }
66
+ const exp = Date.now() + env.sessionDays * 24 * 60 * 60 * 1e3;
67
+ const token = await signSession({ u: env.username, exp }, env.secret);
68
+ const store = await cookies();
69
+ store.set(getStageCookieName(), token, {
70
+ httpOnly: true,
71
+ // secure must be false on HTTP dev (next dev on localhost) so the browser stores
72
+ // the cookie. In production builds (next start / Vercel) this becomes true.
73
+ secure: process.env.NODE_ENV === "production",
74
+ sameSite: "lax",
75
+ path: "/",
76
+ expires: new Date(exp)
77
+ });
78
+ redirect(safeRedirectTarget(formData.get("from")));
79
+ }
80
+ export {
81
+ stageLoginAction
82
+ };
83
+ //# sourceMappingURL=action.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/auth/action.ts","../../src/auth/stage.ts"],"sourcesContent":["// 'use server' is injected by the tsup banner — keep this file directive-free\n// so the bundled output has exactly one directive at the top.\nimport { cookies } from 'next/headers';\nimport { redirect } from 'next/navigation';\nimport { getStageCookieName, readStageEnv, signSession, verifyCredentials } from './stage.js';\n\nexport type StageLoginState = { error?: 'missing_config' | 'invalid_credentials' | null };\n\nfunction safeRedirectTarget(raw: unknown): string {\n if (typeof raw !== 'string' || raw.length === 0) return '/';\n if (!raw.startsWith('/') || raw.startsWith('//')) return '/';\n return raw;\n}\n\nexport async function stageLoginAction(_prev: StageLoginState, formData: FormData): Promise<StageLoginState> {\n const env = readStageEnv();\n if (!env) return { error: 'missing_config' };\n\n const username = formData.get('username');\n const password = formData.get('password');\n if (!verifyCredentials(env, username, password)) {\n return { error: 'invalid_credentials' };\n }\n\n const exp = Date.now() + env.sessionDays * 24 * 60 * 60 * 1000;\n const token = await signSession({ u: env.username, exp }, env.secret);\n\n const store = await cookies();\n store.set(getStageCookieName(), token, {\n httpOnly: true,\n // secure must be false on HTTP dev (next dev on localhost) so the browser stores\n // the cookie. In production builds (next start / Vercel) this becomes true.\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n path: '/',\n expires: new Date(exp),\n });\n\n redirect(safeRedirectTarget(formData.get('from')));\n}\n","// Internal helpers for the stage-environment auth gate.\n// Edge-runtime safe (uses Web Crypto, no Node APIs).\n\nconst COOKIE_NAME = 'olmo_stage_auth';\nconst DEFAULT_SESSION_DAYS = 7;\n\nexport type StagePayload = { u: string; exp: number };\n\nexport type StageEnv = {\n username: string;\n password: string;\n secret: string;\n sessionDays: number;\n};\n\nexport function readStageEnv(): StageEnv | null {\n const username = process.env.OLMO_STAGE_USERNAME;\n const password = process.env.OLMO_STAGE_PASSWORD;\n const secret = process.env.OLMO_STAGE_SECRET;\n if (!username || !password || !secret) return null;\n const days = Number(process.env.OLMO_STAGE_SESSION_DAYS);\n return {\n username,\n password,\n secret,\n sessionDays: Number.isFinite(days) && days > 0 ? days : DEFAULT_SESSION_DAYS,\n };\n}\n\nexport function getStageCookieName(): string {\n return COOKIE_NAME;\n}\n\nfunction toBase64Url(bytes: ArrayBuffer | Uint8Array): string {\n const arr = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);\n let str = '';\n for (let i = 0; i < arr.length; i++) str += String.fromCharCode(arr[i]);\n return btoa(str).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\nfunction fromBase64Url(input: string): Uint8Array {\n const pad = input.length % 4 === 0 ? '' : '='.repeat(4 - (input.length % 4));\n const b64 = input.replace(/-/g, '+').replace(/_/g, '/') + pad;\n const bin = atob(b64);\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\nasync function importKey(secret: string): Promise<CryptoKey> {\n return crypto.subtle.importKey(\n 'raw',\n new TextEncoder().encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign', 'verify'],\n );\n}\n\nexport async function signSession(payload: StagePayload, secret: string): Promise<string> {\n const body = toBase64Url(new TextEncoder().encode(JSON.stringify(payload)));\n const key = await importKey(secret);\n const sig = await crypto.subtle.sign('HMAC', key, new TextEncoder().encode(body));\n return `${body}.${toBase64Url(sig)}`;\n}\n\nexport async function verifySession(token: string | undefined, secret: string): Promise<StagePayload | null> {\n if (!token || typeof token !== 'string' || token.indexOf('.') === -1) return null;\n const [body, sig] = token.split('.');\n if (!body || !sig) return null;\n let key: CryptoKey;\n try {\n key = await importKey(secret);\n } catch {\n return null;\n }\n let valid = false;\n try {\n valid = await crypto.subtle.verify('HMAC', key, fromBase64Url(sig) as BufferSource, new TextEncoder().encode(body));\n } catch {\n return null;\n }\n if (!valid) return null;\n let payload: StagePayload;\n try {\n payload = JSON.parse(new TextDecoder().decode(fromBase64Url(body)));\n } catch {\n return null;\n }\n if (!payload || typeof payload.exp !== 'number' || payload.exp < Date.now()) return null;\n return payload;\n}\n\nexport function verifyCredentials(env: StageEnv, username: unknown, password: unknown): boolean {\n if (typeof username !== 'string' || typeof password !== 'string') return false;\n return username === env.username && password === env.password;\n}\n"],"mappings":";;;AAEA,SAAS,eAAe;AACxB,SAAS,gBAAgB;;;ACAzB,IAAM,cAAc;AACpB,IAAM,uBAAuB;AAWtB,SAAS,eAAgC;AAC9C,QAAM,WAAW,QAAQ,IAAI;AAC7B,QAAM,WAAW,QAAQ,IAAI;AAC7B,QAAM,SAAS,QAAQ,IAAI;AAC3B,MAAI,CAAC,YAAY,CAAC,YAAY,CAAC,OAAQ,QAAO;AAC9C,QAAM,OAAO,OAAO,QAAQ,IAAI,uBAAuB;AACvD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa,OAAO,SAAS,IAAI,KAAK,OAAO,IAAI,OAAO;AAAA,EAC1D;AACF;AAEO,SAAS,qBAA6B;AAC3C,SAAO;AACT;AAEA,SAAS,YAAY,OAAyC;AAC5D,QAAM,MAAM,iBAAiB,aAAa,QAAQ,IAAI,WAAW,KAAK;AACtE,MAAI,MAAM;AACV,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,IAAK,QAAO,OAAO,aAAa,IAAI,CAAC,CAAC;AACtE,SAAO,KAAK,GAAG,EAAE,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,EAAE;AAC5E;AAWA,eAAe,UAAU,QAAoC;AAC3D,SAAO,OAAO,OAAO;AAAA,IACnB;AAAA,IACA,IAAI,YAAY,EAAE,OAAO,MAAM;AAAA,IAC/B,EAAE,MAAM,QAAQ,MAAM,UAAU;AAAA,IAChC;AAAA,IACA,CAAC,QAAQ,QAAQ;AAAA,EACnB;AACF;AAEA,eAAsB,YAAY,SAAuB,QAAiC;AACxF,QAAM,OAAO,YAAY,IAAI,YAAY,EAAE,OAAO,KAAK,UAAU,OAAO,CAAC,CAAC;AAC1E,QAAM,MAAM,MAAM,UAAU,MAAM;AAClC,QAAM,MAAM,MAAM,OAAO,OAAO,KAAK,QAAQ,KAAK,IAAI,YAAY,EAAE,OAAO,IAAI,CAAC;AAChF,SAAO,GAAG,IAAI,IAAI,YAAY,GAAG,CAAC;AACpC;AA6BO,SAAS,kBAAkB,KAAe,UAAmB,UAA4B;AAC9F,MAAI,OAAO,aAAa,YAAY,OAAO,aAAa,SAAU,QAAO;AACzE,SAAO,aAAa,IAAI,YAAY,aAAa,IAAI;AACvD;;;ADxFA,SAAS,mBAAmB,KAAsB;AAChD,MAAI,OAAO,QAAQ,YAAY,IAAI,WAAW,EAAG,QAAO;AACxD,MAAI,CAAC,IAAI,WAAW,GAAG,KAAK,IAAI,WAAW,IAAI,EAAG,QAAO;AACzD,SAAO;AACT;AAEA,eAAsB,iBAAiB,OAAwB,UAA8C;AAC3G,QAAM,MAAM,aAAa;AACzB,MAAI,CAAC,IAAK,QAAO,EAAE,OAAO,iBAAiB;AAE3C,QAAM,WAAW,SAAS,IAAI,UAAU;AACxC,QAAM,WAAW,SAAS,IAAI,UAAU;AACxC,MAAI,CAAC,kBAAkB,KAAK,UAAU,QAAQ,GAAG;AAC/C,WAAO,EAAE,OAAO,sBAAsB;AAAA,EACxC;AAEA,QAAM,MAAM,KAAK,IAAI,IAAI,IAAI,cAAc,KAAK,KAAK,KAAK;AAC1D,QAAM,QAAQ,MAAM,YAAY,EAAE,GAAG,IAAI,UAAU,IAAI,GAAG,IAAI,MAAM;AAEpE,QAAM,QAAQ,MAAM,QAAQ;AAC5B,QAAM,IAAI,mBAAmB,GAAG,OAAO;AAAA,IACrC,UAAU;AAAA;AAAA;AAAA,IAGV,QAAQ,QAAQ,IAAI,aAAa;AAAA,IACjC,UAAU;AAAA,IACV,MAAM;AAAA,IACN,SAAS,IAAI,KAAK,GAAG;AAAA,EACvB,CAAC;AAED,WAAS,mBAAmB,SAAS,IAAI,MAAM,CAAC,CAAC;AACnD;","names":[]}
@@ -22,7 +22,7 @@ async function getting(lang, path, model = "") {
22
22
  return await response.json();
23
23
  } catch (error) {
24
24
  console.error(`[olmo:get] Network error \u2014 ${path}:`, error);
25
- throw error;
25
+ return void 0;
26
26
  }
27
27
  }
28
28
  async function posting(lang = "it", path, body) {
@@ -76,4 +76,4 @@ export {
76
76
  posting,
77
77
  filter
78
78
  };
79
- //# sourceMappingURL=chunk-JISDMUJ3.js.map
79
+ //# sourceMappingURL=chunk-DMHYDI2A.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 return undefined;\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,WAAO;AAAA,EACT;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,168 @@
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
+ // src/middleware/stagegatemiddleware.ts
62
+ import { NextResponse as NextResponse3 } from "next/server";
63
+
64
+ // src/auth/stage.ts
65
+ var COOKIE_NAME = "olmo_stage_auth";
66
+ var DEFAULT_SESSION_DAYS = 7;
67
+ function readStageEnv() {
68
+ const username = process.env.OLMO_STAGE_USERNAME;
69
+ const password = process.env.OLMO_STAGE_PASSWORD;
70
+ const secret = process.env.OLMO_STAGE_SECRET;
71
+ if (!username || !password || !secret) return null;
72
+ const days = Number(process.env.OLMO_STAGE_SESSION_DAYS);
73
+ return {
74
+ username,
75
+ password,
76
+ secret,
77
+ sessionDays: Number.isFinite(days) && days > 0 ? days : DEFAULT_SESSION_DAYS
78
+ };
79
+ }
80
+ function getStageCookieName() {
81
+ return COOKIE_NAME;
82
+ }
83
+ function fromBase64Url(input) {
84
+ const pad = input.length % 4 === 0 ? "" : "=".repeat(4 - input.length % 4);
85
+ const b64 = input.replace(/-/g, "+").replace(/_/g, "/") + pad;
86
+ const bin = atob(b64);
87
+ const out = new Uint8Array(bin.length);
88
+ for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
89
+ return out;
90
+ }
91
+ async function importKey(secret) {
92
+ return crypto.subtle.importKey(
93
+ "raw",
94
+ new TextEncoder().encode(secret),
95
+ { name: "HMAC", hash: "SHA-256" },
96
+ false,
97
+ ["sign", "verify"]
98
+ );
99
+ }
100
+ async function verifySession(token, secret) {
101
+ if (!token || typeof token !== "string" || token.indexOf(".") === -1) return null;
102
+ const [body, sig] = token.split(".");
103
+ if (!body || !sig) return null;
104
+ let key;
105
+ try {
106
+ key = await importKey(secret);
107
+ } catch {
108
+ return null;
109
+ }
110
+ let valid = false;
111
+ try {
112
+ valid = await crypto.subtle.verify("HMAC", key, fromBase64Url(sig), new TextEncoder().encode(body));
113
+ } catch {
114
+ return null;
115
+ }
116
+ if (!valid) return null;
117
+ let payload;
118
+ try {
119
+ payload = JSON.parse(new TextDecoder().decode(fromBase64Url(body)));
120
+ } catch {
121
+ return null;
122
+ }
123
+ if (!payload || typeof payload.exp !== "number" || payload.exp < Date.now()) return null;
124
+ return payload;
125
+ }
126
+
127
+ // src/middleware/stagegatemiddleware.ts
128
+ var LOGIN_PATH = "/olmo-stage-login/";
129
+ var NOINDEX = "noindex, nofollow, noarchive";
130
+ function withNoindex(res) {
131
+ res.headers.set("X-Robots-Tag", NOINDEX);
132
+ return res;
133
+ }
134
+ var stagegatemiddleware = (next) => {
135
+ return async (request, _next) => {
136
+ if (process.env.NEXT_PUBLIC_ENV !== "stage") {
137
+ return next(request, _next);
138
+ }
139
+ const { pathname, search } = request.nextUrl;
140
+ if (pathname === LOGIN_PATH) {
141
+ return withNoindex(NextResponse3.next());
142
+ }
143
+ const env = readStageEnv();
144
+ if (!env) {
145
+ const url2 = request.nextUrl.clone();
146
+ url2.pathname = LOGIN_PATH;
147
+ url2.search = "";
148
+ return withNoindex(NextResponse3.redirect(url2, { status: 307 }));
149
+ }
150
+ const token = request.cookies.get(getStageCookieName())?.value;
151
+ const session = await verifySession(token, env.secret);
152
+ if (session) {
153
+ const res = await next(request, _next);
154
+ return withNoindex(res instanceof NextResponse3 ? res : NextResponse3.next());
155
+ }
156
+ const url = request.nextUrl.clone();
157
+ url.pathname = LOGIN_PATH;
158
+ return withNoindex(NextResponse3.redirect(url, { status: 307 }));
159
+ };
160
+ };
161
+
162
+ export {
163
+ chain,
164
+ headermiddleware,
165
+ redirectmiddleware,
166
+ stagegatemiddleware
167
+ };
168
+ //# sourceMappingURL=chunk-RAI2AUWN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/middleware/chain.ts","../src/middleware/headermiddleware.ts","../src/middleware/redirectmiddleware.ts","../src/middleware/stagegatemiddleware.ts","../src/auth/stage.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","import { NextResponse } from 'next/server';\nimport type { NextFetchEvent, NextRequest } from 'next/server';\nimport { getStageCookieName, readStageEnv, verifySession } from '../auth/stage.js';\nimport type { MiddlewareFactory } from './chain.js';\n\nconst LOGIN_PATH = '/olmo-stage-login/';\nconst NOINDEX = 'noindex, nofollow, noarchive';\n\nfunction withNoindex(res: NextResponse): NextResponse {\n res.headers.set('X-Robots-Tag', NOINDEX);\n return res;\n}\n\nexport const stagegatemiddleware: MiddlewareFactory = (next) => {\n return async (request: NextRequest, _next: NextFetchEvent) => {\n if (process.env.NEXT_PUBLIC_ENV !== 'stage') {\n return next(request, _next);\n }\n\n const { pathname, search } = request.nextUrl;\n\n if (pathname === LOGIN_PATH) {\n return withNoindex(NextResponse.next());\n }\n\n const env = readStageEnv();\n if (!env) {\n // Misconfigured stage — deny everything except the login page itself.\n const url = request.nextUrl.clone();\n url.pathname = LOGIN_PATH;\n url.search = '';\n return withNoindex(NextResponse.redirect(url, { status: 307 }));\n }\n\n const token = request.cookies.get(getStageCookieName())?.value;\n const session = await verifySession(token, env.secret);\n if (session) {\n const res = await next(request, _next);\n return withNoindex(res instanceof NextResponse ? res : NextResponse.next());\n }\n\n const url = request.nextUrl.clone();\n url.pathname = LOGIN_PATH;\n // url.search = `?from=${encodeURIComponent(pathname + search)}`;\n return withNoindex(NextResponse.redirect(url, { status: 307 }));\n };\n};\n","// Internal helpers for the stage-environment auth gate.\n// Edge-runtime safe (uses Web Crypto, no Node APIs).\n\nconst COOKIE_NAME = 'olmo_stage_auth';\nconst DEFAULT_SESSION_DAYS = 7;\n\nexport type StagePayload = { u: string; exp: number };\n\nexport type StageEnv = {\n username: string;\n password: string;\n secret: string;\n sessionDays: number;\n};\n\nexport function readStageEnv(): StageEnv | null {\n const username = process.env.OLMO_STAGE_USERNAME;\n const password = process.env.OLMO_STAGE_PASSWORD;\n const secret = process.env.OLMO_STAGE_SECRET;\n if (!username || !password || !secret) return null;\n const days = Number(process.env.OLMO_STAGE_SESSION_DAYS);\n return {\n username,\n password,\n secret,\n sessionDays: Number.isFinite(days) && days > 0 ? days : DEFAULT_SESSION_DAYS,\n };\n}\n\nexport function getStageCookieName(): string {\n return COOKIE_NAME;\n}\n\nfunction toBase64Url(bytes: ArrayBuffer | Uint8Array): string {\n const arr = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);\n let str = '';\n for (let i = 0; i < arr.length; i++) str += String.fromCharCode(arr[i]);\n return btoa(str).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\nfunction fromBase64Url(input: string): Uint8Array {\n const pad = input.length % 4 === 0 ? '' : '='.repeat(4 - (input.length % 4));\n const b64 = input.replace(/-/g, '+').replace(/_/g, '/') + pad;\n const bin = atob(b64);\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\nasync function importKey(secret: string): Promise<CryptoKey> {\n return crypto.subtle.importKey(\n 'raw',\n new TextEncoder().encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign', 'verify'],\n );\n}\n\nexport async function signSession(payload: StagePayload, secret: string): Promise<string> {\n const body = toBase64Url(new TextEncoder().encode(JSON.stringify(payload)));\n const key = await importKey(secret);\n const sig = await crypto.subtle.sign('HMAC', key, new TextEncoder().encode(body));\n return `${body}.${toBase64Url(sig)}`;\n}\n\nexport async function verifySession(token: string | undefined, secret: string): Promise<StagePayload | null> {\n if (!token || typeof token !== 'string' || token.indexOf('.') === -1) return null;\n const [body, sig] = token.split('.');\n if (!body || !sig) return null;\n let key: CryptoKey;\n try {\n key = await importKey(secret);\n } catch {\n return null;\n }\n let valid = false;\n try {\n valid = await crypto.subtle.verify('HMAC', key, fromBase64Url(sig) as BufferSource, new TextEncoder().encode(body));\n } catch {\n return null;\n }\n if (!valid) return null;\n let payload: StagePayload;\n try {\n payload = JSON.parse(new TextDecoder().decode(fromBase64Url(body)));\n } catch {\n return null;\n }\n if (!payload || typeof payload.exp !== 'number' || payload.exp < Date.now()) return null;\n return payload;\n}\n\nexport function verifyCredentials(env: StageEnv, username: unknown, password: unknown): boolean {\n if (typeof username !== 'string' || typeof password !== 'string') return false;\n return username === env.username && password === env.password;\n}\n"],"mappings":"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","names":["NextResponse","NextResponse","NextResponse","url"]}
package/dist/cli/index.js CHANGED
@@ -250,7 +250,7 @@ var addRouteCommand = new Command("route").description("Scaffold a new Olmo page
250
250
  { title: "List page (fetches a collection)", value: "list" },
251
251
  { title: "Single/detail page (slug route)", value: "single" }
252
252
  ],
253
- initial: defaultType === "list" ? 1 : defaultType === "single" ? 2 : 0
253
+ initial: defaultType === "single" ? 2 : 0
254
254
  });
255
255
  if (!res.value) process.exit(0);
256
256
  routeType = res.value;
@@ -48,7 +48,7 @@ async function getting(lang, path, model = "") {
48
48
  return await response.json();
49
49
  } catch (error) {
50
50
  console.error(`[olmo:get] Network error \u2014 ${path}:`, error);
51
- throw error;
51
+ return void 0;
52
52
  }
53
53
  }
54
54
  async function posting(lang = "it", path, body) {
@@ -1 +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":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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":[]}
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 return undefined;\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":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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,WAAO;AAAA,EACT;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":[]}
@@ -2,7 +2,7 @@ import {
2
2
  filter,
3
3
  getting,
4
4
  posting
5
- } from "../chunk-JISDMUJ3.js";
5
+ } from "../chunk-DMHYDI2A.js";
6
6
  export {
7
7
  filter,
8
8
  getting,