updated docs

This commit is contained in:
2026-08-12 17:54:40 +02:00
parent 4eedc1f642
commit 195d4169f5
7 changed files with 287 additions and 134 deletions
+3 -1
View File
@@ -95,7 +95,7 @@ export default buildConfig({
| `@intecion/ipal-kit/server` | runtime server-only (sendEmail, verifyTurnstile, submitForm) | Server Actions / route handlers |
| `@intecion/ipal-kit/client` | komponenty client (consent, Turnstile, Analytics) | `'use client'` |
| `@intecion/ipal-kit/rsc` | RenderBlocks (RSC) | server component |
| `@intecion/ipal-kit/next/middleware` | locale middleware | middleware.ts / proxy.ts |
| `@intecion/ipal-kit/next/middleware` | locale middleware (import bez zmian) | `proxy.ts` (Next 16; dawniej `middleware.ts`) |
## Moduły
@@ -118,6 +118,8 @@ export default buildConfig({
Nowy projekt krok po kroku: [getting-started.md](./getting-started.md)
Referencja wdrożenia frontu: [frontend-setup.md](./frontend-setup.md)
Wydawanie nowych wersji wtyczki: [publishing.md](./publishing.md)
Jak komendy łączą się z Gitea (dla instalujących): [gitea-commands.md](./gitea-commands.md)
Working with a project repo on Gitea (clone/pull/push): [gitea-workflow.md](./gitea-workflow.md) · [🇵🇱 PL](./gitea-workflow.pl.md)
## Zasady dla wszystkich modułów
+86
View File
@@ -0,0 +1,86 @@
# Jak komendy rozmawiają z git.intecion.net
Ten plik tłumaczy, co robi każda komenda, gdy instalujesz `@intecion/ipal-kit`.
Rejestr pakietów jest **publiczny do odczytu** — instalacja nie wymaga tokenu.
Token jest potrzebny tylko przy publikowaniu nowych wersji (patrz
[publishing.md](./publishing.md)).
## Rejestr scoped — co to znaczy
W `.npmrc` masz jedną linię:
```
@intecion:registry=https://git.intecion.net/api/packages/IntecionSoftware/npm/
```
To reguła: „pakiety zaczynające się od `@intecion/` pobieraj z tego adresu".
**Nie zmienia** domyślnego rejestru — wszystko inne (`react`, `next`,
`@payloadcms/*`) dalej idzie z publicznego npm. To override dla jednego scope,
nie przełączenie całego źródła.
Dlatego mieszana instalacja działa bez konfliktu:
- `@intecion/ipal-kit` → Gitea
- `react`, `payload`, `lucide-react` → npm
## Komenda po komendzie
### edycja `.npmrc` (linia z registry)
**Co robi:** zapisuje regułę „scope `@intecion` → rejestr Gitea". Nic nie
pobiera — to plik konfiguracyjny, czytany dopiero przy instalacji.
**Rozmowa z serwerem:** żadna przy samym zapisie.
Ponieważ rejestr jest publiczny, ta linia **nie zawiera tokenu** — plik jest
bezpieczny do zacommitowania i musi trafić do repo, żeby serwer deploymentu też
wiedział, skąd brać `@intecion/*`.
### `pnpm add @intecion/ipal-kit`
**Co robi:** to komenda, która faktycznie łączy się z rejestrem.
Krok po kroku:
1. pnpm widzi scope `@intecion` → sprawdza `.npmrc` → znajduje regułę „→ Gitea".
2. Łączy się z rejestrem Gitea. Rejestr publiczny, więc **bez tokenu**.
3. Rejestr odsyła metadane pakietu (wersje, adres `.tgz`).
4. pnpm pobiera i rozpakowuje do `node_modules/@intecion/ipal-kit` — **czysta
ścieżka**, bez hasha commita.
Ta czysta ścieżka jest ważna: komponenty klienta pluginu (baner zgód, analytics,
Turnstile) rozwiązują się poprawnie tylko z niej. Instalacja z gita dawała
pokręconą ścieżkę z hashem, która łamała React Client Manifest.
**Gdy to zawiedzie:**
- `404` — brakuje linii `@intecion:registry` w `.npmrc`, więc pnpm poszedł do
publicznego npm, gdzie pakietu nie ma. Sprawdź, czy `.npmrc` istnieje i ma tę
linię.
### `pnpm install`
**Co robi:** odtwarza wszystkie zależności z `package.json` / lockfile, w tym
`@intecion/ipal-kit`. Ta sama rozmowa z Gitea dla części `@intecion`, reszta z
npm. Różnica względem `add`: `install` odtwarza to, co już zapisane, `add`
dopisuje nowe.
## Sprawdzenie, czy rejestr odpowiada
Bez tokenu, publiczny endpoint:
```bash
curl -s -o /dev/null -w "%{http_code}\n" \
https://git.intecion.net/api/packages/IntecionSoftware/npm/@intecion%2Fipal-kit
```
`200` → rejestr działa, pakiet dostępny. `404` → zła ścieżka/nazwa.
## Krótkie podsumowanie
| Komenda | Rozmawia z serwerem? | Token? | Po co |
|---|---|---|---|
| edycja `.npmrc` (registry) | nie | nie | reguła scope na później |
| `pnpm add @intecion/ipal-kit` | tak | nie (publiczny) | pobiera pakiet |
| `pnpm install` | tak (dla @intecion) | nie | odtwarza zależności |
| `curl .../npm/@intecion%2F...` | tak | nie | test dostępności |
Publikowanie wersji (osobna rola, **wymaga** tokenu `write:package`):
[publishing.md](./publishing.md).
+116
View File
@@ -0,0 +1,116 @@
# Wydawanie nowej wersji
> **Instalacja jest publiczna** — rejestr Gitea pozwala pobierać pakiety bez
> tokenu. Ten plik dotyczy **publikowania** nowych wersji, co wymaga tokenu
> `write:package`. Instrukcja instalacji: główny [README](../README.md).
Dla osób rozwijających samą wtyczkę. Instalacja (dla użytkowników) jest w głównym
[README](../README.md) — ten plik dotyczy publikowania kolejnych wersji do
rejestru Gitea.
## package.json — co musi się zgadzać
Przed pierwszą publikacją sprawdź, że manifest jest poprawny — te pola były
źródłem większości problemów przy dystrybucji:
```json
{
"name": "@intecion/ipal-kit",
"version": "1.0.0",
"files": ["dist"],
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": { "...": "wszystkie subpath na ./dist/*.js i ./dist/*.d.ts" },
"publishConfig": {
"registry": "https://git.intecion.net/api/packages/IntecionSoftware/npm/"
}
}
```
Kontrola przed publikacją:
```bash
grep -c '"exports"' package.json # 1 — jeden blok, nie dwa
grep -c "git+https.*ipal-kit" package.json # 0 — brak self-reference
grep '"import"' package.json | head -1 # ./dist/ — nie ./src/
node -e "JSON.parse(require('fs').readFileSync('package.json','utf8'))" # bez błędu
```
- **`exports` na `dist`, nie `src`** — jeden blok, wszystkie ścieżki na `./dist/`.
- **jeden blok `exports`** — nie zostawiaj drugiego (np. w starym
`publishConfig.exports`); dwa bloki rozjeżdżają rozwiązywanie modułów.
- **brak self-reference** — pakiet nie może mieć siebie w `dependencies`.
Wchodzi, gdy odpalisz `pnpm add` w katalogu wtyczki — **nigdy tego nie rób**.
- **peer, nie dependencies** — `payload`, `next`, `react`,
`@payloadcms/plugin-seo`, `@payloadcms/plugin-form-builder` w
`peerDependencies`. W `dependencies` inaczej zaciągną drugą kopię Payloada.
## Rejestr — droga zalecana
Rejestr npm w Gitea. Pracownicy pobierają gotowy `dist`, nie budują u siebie.
**Token** z zakresem `write:package` (Gitea → Settings → Applications), w
globalnym `.npmrc` (ścieżka zależna od systemu — patrz tabela w głównym
[README](../README.md#route-a--from-the-registry-recommended); na Windows to
`%USERPROFILE%\.npmrc`):
```
//git.intecion.net/api/packages/IntecionSoftware/npm/:_authToken=${GITEA_TOKEN}
```
**Wydanie:**
```bash
pnpm clean && pnpm build
npm version patch # 1.0.0 → 1.0.1 (minor/major wg zmian)
npm publish
```
Podnoś wersję przy każdym wydaniu — pnpm rozpoznaje pakiet po numerze, więc nowy
numer znosi cały cykl czyszczenia pamięci podręcznej, który męczy przy
zostawaniu na jednej wersji.
## Alternatywa — dystrybucja z repozytorium (bez rejestru)
Jeśli nie publikujesz do rejestru, a instalujesz bezpośrednio z Gitea
(`git+https://...`), obowiązują dodatkowe reguły:
- **`dist/` musi być zacommitowany** w repozytorium — instalacja z git nie
buduje pakietu. Buduj i commituj `dist` przed każdym wydaniem:
```bash
pnpm build
git add -f dist/ # -f, jeśli .gitignore normalnie ignoruje dist
git commit -m "build dist"
git push
```
- **BRAK `prepare: pnpm build`** w package.json — inaczej pnpm próbuje budować
przy instalacji i żąda `onlyBuiltDependencies`.
- **sprawdzaj repozytorium, nie plik lokalny** — pnpm z git bierze stan repo:
```bash
git show origin/main:package.json | grep '"import"' | head -1 # ./dist/
```
Commit z nazwą „fix" nie znaczy, że poprawka jest w commicie.
## Weryfikacja po publikacji
W czystym projekcie testowym:
```bash
pnpm store prune
pnpm add @intecion/ipal-kit # albo git+https://... dla drogi repo
node -e "console.log(require.resolve('@intecion/ipal-kit/next/middleware'))"
```
Ostatnia komenda ma wypisać ścieżkę do `dist/exports/next-middleware.js` — nie
błąd. Jeśli pokazuje `src/...ts`, główny `exports` wskazuje źródła zamiast builda.
## Diagnostyka
| Objaw | Przyczyna |
|---|---|
| `Cannot find module .../src/...ts` | główny `exports` na `src`; przy instalacji z git `publishConfig` jest ignorowane |
| Turbopack „Module not found" mimo pliku na dysku | dwa bloki `exports`; Node bierze zły |
| `ENOENT ...ipal-kit.tgz` | self-reference w `dependencies` |
| `ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED` | `prepare` w package.json (droga repo) |
| stary kod mimo reinstall | pamięć podręczna; podnieś wersję albo `pnpm store prune` + `rm -rf .next node_modules/@intecion` |
+9 -7
View File
@@ -91,20 +91,21 @@ export const i18nConfig = {
} as const // as const — inaczej TS: locales nie pasuje do niepustej tuple
```
Importuj w: payload.config (ipalKit({ i18n: i18nConfig })), middleware.ts.
Importuj w: payload.config (ipalKit({ i18n: i18nConfig })), proxy.ts.
Layout może czytać locale z payload config (config.localization.locales) —
też jedno źródło.
## Middleware
## Proxy (dawniej middleware)
> **Next 16:** konwencja `middleware.ts` jest deprecated na rzecz `proxy.ts`
> (plik `proxy.ts`, funkcja `export function proxy`). Logika pluginu bez zmian —
> `createLocaleMiddleware` działa tak samo, zmienia się tylko nazwa pliku i
> funkcji po stronie projektu. Na razie `middleware.ts` działa z ostrzeżeniem.
> funkcji po stronie projektu. Migracja jedną komendą:
> `npx @next/codemod@canary middleware-to-proxy .`
```ts
// src/middleware.ts
// src/proxy.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
import { createLocaleMiddleware } from '@intecion/ipal-kit/next/middleware'
@@ -112,16 +113,17 @@ import { i18nConfig } from '@/i18n.config'
const localeMiddleware = createLocaleMiddleware({ config: i18nConfig })
export function middleware(request: NextRequest) {
export function proxy(request: NextRequest) {
const result = localeMiddleware(request)
if (result.type === 'next') return NextResponse.next()
const response = NextResponse.redirect(result.location)
response.cookies.set(result.cookie.name, result.cookie.value)
// cookie tylko gdy jest zgoda na kategorię functional — inaczej undefined
if (result.cookie) response.cookies.set(result.cookie.name, result.cookie.value)
return response
}
// matcher MUSI być inline (Next analizuje statycznie, nie wykonuje importów —
// import DEFAULT_MIDDLEWARE_MATCHER byłby zignorowany → middleware łapie
// import DEFAULT_MIDDLEWARE_MATCHER byłby zignorowany → proxy łapie
// /admin /_next /api → 500)
export const config = {
matcher: ['/((?!api|admin|_next|.*\\..*).*)'],
+15 -5
View File
@@ -187,10 +187,15 @@ export default { plugins: { '@tailwindcss/postcss': {} } }
niego klasy komponentów pluginu nie powstaną i banner wyrenderuje się goły.
Ścieżka jest relatywna do pliku CSS.
## 8. Middleware
## 8. Proxy (dawniej middleware)
> **Next 16:** konwencja `middleware.ts` jest przestarzała — nazwa pliku to teraz
> `proxy.ts`, a funkcja `proxy` zamiast `middleware`. Logika pluginu bez zmian:
> `createLocaleMiddleware` działa tak samo. Migracja jednej komendy:
> `npx @next/codemod@canary middleware-to-proxy .`
```ts
// src/middleware.ts
// src/proxy.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
import { createLocaleMiddleware } from '@intecion/ipal-kit/next/middleware'
@@ -198,23 +203,28 @@ import { i18nConfig } from '@/i18n.config'
const localeMiddleware = createLocaleMiddleware({ config: i18nConfig })
export function middleware(request: NextRequest) {
export function proxy(request: NextRequest) {
const result = localeMiddleware(request)
if (result.type === 'next') return NextResponse.next()
const response = NextResponse.redirect(result.location)
response.cookies.set(result.cookie.name, result.cookie.value)
// cookie tylko gdy jest zgoda na kategorię functional — inaczej undefined
if (result.cookie) response.cookies.set(result.cookie.name, result.cookie.value)
return response
}
// INLINE, nie import — Next analizuje ten obiekt statycznie i nie wykonuje
// importów. Importowana stała zostanie zignorowana, middleware złapie /admin
// importów. Importowana stała zostanie zignorowana, proxy złapie /admin
// i /_next, i wszystko zwróci 500.
export const config = {
matcher: ['/((?!api|admin|_next|.*\\..*).*)'],
}
```
> Import z pluginu zostaje `@intecion/ipal-kit/next/middleware` — to nazwa
> subpath eksportu w pakiecie, niezależna od tego, czy plik projektu nazywa się
> `middleware.ts` czy `proxy.ts`.
## 9. Warstwa dostępu do danych
Next uruchamia `generateMetadata` i komponent strony niezależnie — `cache()`
+10 -5
View File
@@ -69,13 +69,18 @@ fallback na `/{locale}` (root), zamiast dead-endu na 404.
## Middleware — patrz osobno
Negocjacja locale + redirect na wejściu (`domena.com` → `/pl`) jest w
`@intecion/ipal-kit/next/middleware`. Zobacz [middleware w tej sekcji](#middleware)
`@intecion/ipal-kit/next/middleware`. Zobacz [proxy w tej sekcji](#proxy-dawniej-middleware)
niżej.
## Middleware
## Proxy (dawniej middleware)
> **Next 16:** plik nazywa się teraz `proxy.ts`, funkcja `proxy`. Import z
> pluginu (`@intecion/ipal-kit/next/middleware`) bez zmian — to nazwa subpath
> eksportu, niezależna od nazwy pliku projektu. Migracja:
> `npx @next/codemod@canary middleware-to-proxy .`
```ts
// middleware.ts (projekt klienta) — jedyna logika to podłączenie
// proxy.ts (projekt klienta) — jedyna logika to podłączenie
import { NextResponse } from 'next/server'
import { createLocaleMiddleware, DEFAULT_MIDDLEWARE_MATCHER } from '@intecion/ipal-kit/next/middleware'
@@ -85,11 +90,11 @@ const i18nConfig = {
}
const localeMiddleware = createLocaleMiddleware({ config: i18nConfig })
export function middleware(req) {
export function proxy(req) {
const r = localeMiddleware(req)
if (r.type === 'next') return NextResponse.next()
const res = NextResponse.redirect(r.location)
res.cookies.set(r.cookie.name, r.cookie.value)
if (r.cookie) res.cookies.set(r.cookie.name, r.cookie.value)
return res
}