universal-ad-loader 0.1.0 → 0.1.1

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/docs/libreria.md CHANGED
@@ -1,20 +1,20 @@
1
- # UAL come libreria: componenti per React, Next.js, Vue e Astro
1
+ # UAL as a library: components for React, Next.js, Vue and Astro
2
2
 
3
- Oltre al tag `<script>` (CDN), UAL si può usare come pacchetto: import sicuro anche sul server, componenti per i framework, tipi TypeScript. Stessa configurazione e stesso comportamento del tag.
3
+ Besides the `<script>` tag (CDN), UAL can be used as a package: server-safe import, framework components, TypeScript types. Same configuration and same behavior as the tag.
4
4
 
5
- > **Stato:** il pacchetto `universal-ad-loader` è pronto ma **non ancora pubblicato su npm** (come pubblicarlo: `pubblicazione-npm.md`). Per provarlo ora: `npm pack` nella cartella del loader e `npm i ./universal-ad-loader-0.1.0.tgz` nel progetto, oppure `npm i /percorso/universal-ad-loader`.
5
+ > **Status:** the package is **published on npm**: `npm i universal-ad-loader` (version 0.1.0, MIT).
6
6
 
7
- ## Quando conviene cosa
7
+ ## When to use what
8
8
 
9
- | | Tag `<script>` dalla CDN | Pacchetto (componenti) |
9
+ | | `<script>` tag from the CDN | Package (components) |
10
10
  |---|---|---|
11
- | Siti senza build (HTML, WordPress) | ✅ | — |
12
- | Siti React / Next / Vue / Astro | funziona, con attenzioni (sotto) | ✅ consigliato |
13
- | Idratazione e cambio pagina | a carico tuo | gestiti dai componenti |
14
- | Tipi e completamento della config | — | ✅ `defineConfig` |
15
- | Aggiornare loader/config senza rideploy | ✅ | ✅ con `src` (loader) e `config` come URL |
11
+ | Sites without a build step (HTML, WordPress) | ✅ | — |
12
+ | React / Next / Vue / Astro sites | works, with caveats (below) | ✅ recommended |
13
+ | Hydration and page changes | up to you | handled by the components |
14
+ | Config types and autocompletion | — | ✅ `defineConfig` |
15
+ | Updating loader/config without a redeploy | ✅ | ✅ with `src` (loader) and `config` as a URL |
16
16
 
17
- I componenti supportano entrambi i modelli: il **loader** si prende dalla CDN (`src="…/ual.min.js"`) oppure è incluso nel bundle del sito; la **configurazione** è un URL (modifiche senza rideploy) oppure un oggetto nel codice.
17
+ The components support both models: the **loader** comes from the CDN (`src="…/ual.min.js"`) or is included in the site bundle; the **configuration** is a URL (changes without a redeploy) or an object in the code.
18
18
 
19
19
  ## React
20
20
 
@@ -23,13 +23,13 @@ import { UalProvider, AdSlot } from 'universal-ad-loader/react';
23
23
  import { defineConfig } from 'universal-ad-loader';
24
24
 
25
25
  const config = defineConfig({
26
- site: 'mio-sito',
27
- providers: { main: { adapter: 'json', endpoint: 'https://ads.tuodominio.net/v1/decide' } },
26
+ site: 'my-site',
27
+ providers: { main: { adapter: 'json', endpoint: 'https://ads.yourdomain.net/v1/decide' } },
28
28
  slots: { top: { sizes: [[728, 90]], providers: ['main'] } },
29
29
  });
30
30
 
31
31
  export function App() {
32
- const { pathname } = useLocation(); // react-router, o il tuo router
32
+ const { pathname } = useLocation(); // react-router, or your own router
33
33
  return (
34
34
  <UalProvider config={config} pageKey={pathname}>
35
35
  <AdSlot name="top" minHeight={90} />
@@ -38,17 +38,17 @@ export function App() {
38
38
  }
39
39
  ```
40
40
 
41
- - `config`: oggetto o URL del JSON (letto solo all'avvio).
42
- - `src`: URL del loader su CDN; senza, UAL è incluso nel bundle del sito.
43
- - `pageKey`: quando cambia (percorso), UAL ricalcola regole per pagina e slot.
44
- - `targeting`: coppie chiave/valore, anche dinamiche.
45
- - `onEvent(evento, dati)`: tutti gli eventi (`ready`, `consent`, `slotRendered`, `slotEmpty`, `error`…), compresi quelli iniziali.
46
- - `useUal()`: `{ ual, ready }` (`ual` è `null` sul server e prima dell'avvio).
47
- - `AdSlot`: `name`, `params`, `minHeight`, `className`, `style`, `id`. È un `div` vuoto: UAL lo riempie.
41
+ - `config`: object or JSON URL (read only at startup).
42
+ - `src`: URL of the loader on the CDN; without it, UAL is included in the site bundle.
43
+ - `pageKey`: when it changes (path), UAL recomputes the per-page rules and slots.
44
+ - `targeting`: key/value pairs, also dynamic ones.
45
+ - `onEvent(event, data)`: all events (`ready`, `consent`, `slotRendered`, `slotEmpty`, `error`…), including the initial ones.
46
+ - `useUal()`: `{ ual, ready }` (`ual` is `null` on the server and before startup).
47
+ - `AdSlot`: `name`, `params`, `minHeight`, `className`, `style`, `id`. It is an empty `div`: UAL fills it.
48
48
 
49
49
  ## Next.js
50
50
 
51
- Stessi componenti da `universal-ad-loader/next`: il cambio pagina è automatico (`usePathname`). Funziona con App Router e importato da un Server Component (i file hanno `'use client'`).
51
+ Same components from `universal-ad-loader/next`: page changes are automatic (`usePathname`). Works with the App Router and when imported from a Server Component (the files have `'use client'`).
52
52
 
53
53
  ```jsx
54
54
  // app/layout.jsx (Server Component)
@@ -59,7 +59,7 @@ const config = defineConfig({ /* … */ });
59
59
 
60
60
  export default function RootLayout({ children }) {
61
61
  return (
62
- <html lang="it"><body>
62
+ <html lang="en"><body>
63
63
  <UalProvider config={config}>{children}</UalProvider>
64
64
  </body></html>
65
65
  );
@@ -70,7 +70,7 @@ import { AdSlot } from 'universal-ad-loader/next';
70
70
  export default function Page() { return <AdSlot name="top" minHeight={90} />; }
71
71
  ```
72
72
 
73
- ## Vue 3 e Nuxt
73
+ ## Vue 3 and Nuxt
74
74
 
75
75
  ```vue
76
76
  <script setup>
@@ -87,16 +87,16 @@ const config = { /* … */ };
87
87
  </template>
88
88
  ```
89
89
 
90
- Stesse prop (kebab-case) e stesso `useUal()` (con ref). UAL parte in `onMounted`: solo nel browser e dopo l'idratazione. Il rendering sul server di Vue è verificato dai test; **Nuxt non è stato provato** (il provider va messo in `app.vue`, dove vive il layout).
90
+ Same props (kebab-case) and same `useUal()` (with refs). UAL starts in `onMounted`: browser only and after hydration. Vue server rendering is verified by the tests; **Nuxt has not been tried** (the provider goes in `app.vue`, where the layout lives).
91
91
 
92
92
  ## Astro
93
93
 
94
- Gli slot nelle pagine `.astro` sono HTML statico: nessuna idratazione.
94
+ Slots in `.astro` pages are static HTML: no hydration.
95
95
 
96
96
  ```astro
97
97
  ---
98
- import UalBundled from 'universal-ad-loader/astro/UalBundled.astro'; // UAL nel bundle del sito
99
- // oppure: import UalLoader from 'universal-ad-loader/astro/UalLoader.astro'; // loader dalla CDN
98
+ import UalBundled from 'universal-ad-loader/astro/UalBundled.astro'; // UAL in the site bundle
99
+ // or: import UalLoader from 'universal-ad-loader/astro/UalLoader.astro'; // loader from the CDN
100
100
  import AdSlot from 'universal-ad-loader/astro/AdSlot.astro';
101
101
  import { config } from '../config';
102
102
  ---
@@ -104,39 +104,39 @@ import { config } from '../config';
104
104
  <body><AdSlot name="top" minHeight={90} /></body>
105
105
  ```
106
106
 
107
- - `UalBundled`: la configurazione sta in un blocco `application/json` (non eseguito: compatibile con una CSP rigida) e UAL è incluso nel bundle.
108
- - `UalLoader` (`src`, `config`): carica `ual.min.js` dalla CDN, con la config come URL o come oggetto.
109
- - Entrambi, con le View Transitions (`ClientRouter`), ricalcolano le regole per pagina a ogni navigazione.
107
+ - `UalBundled`: the configuration lives in an `application/json` block (not executed: compatible with a strict CSP) and UAL is included in the bundle.
108
+ - `UalLoader` (`src`, `config`): loads `ual.min.js` from the CDN, with the config as a URL or an object.
109
+ - Both, with View Transitions (`ClientRouter`), recompute the per-page rules on every navigation.
110
110
 
111
- ## Nucleo e Node
111
+ ## Core and Node
112
112
 
113
113
  ```js
114
114
  import { createUal, getUal, defineConfig, version } from 'universal-ad-loader';
115
115
  ```
116
116
 
117
- - **Nessun effetto collaterale all'import:** si può importare in Node, in un Server Component, in un file di configurazione. Il DOM si tocca solo quando si chiama `init()` nel browser.
118
- - `getUal()`: l'istanza condivisa della pagina. Sul server lancia un errore chiaro: chiamalo dopo il montaggio.
119
- - `createUal()`: una nuova istanza (utile nei test).
120
- - `defineConfig(config)`: identità con i tipi. **Segnala un provider inesistente nel waterfall** di uno slot.
117
+ - **No side effects on import:** it can be imported in Node, in a Server Component, in a config file. The DOM is only touched when `init()` is called in the browser.
118
+ - `getUal()`: the page's shared instance. On the server it throws a clear error: call it after mounting.
119
+ - `createUal()`: a new instance (useful in tests).
120
+ - `defineConfig(config)`: identity function with types. **It flags a nonexistent provider in a slot's waterfall**.
121
121
 
122
- Il rendering sul server produce solo i `div` degli slot (con `min-height` se indicato: nessun salto di layout). Gli annunci arrivano nel browser.
122
+ Server rendering produces only the slot `div`s (with `min-height` if specified: no layout shift). Ads arrive in the browser.
123
123
 
124
- ## Cosa gestiscono i componenti (e il tag no)
124
+ ## What the components handle (and the tag does not)
125
125
 
126
- - **Idratazione.** UAL parte in un effect, dopo l'idratazione. Caricare invece il loader con un tag nell'HTML prima dell'idratazione fa segnalare a React *Hydration failed* (anche con `suppressHydrationWarning`) e fa richiedere lo slot **due volte**: il test del repository lo riproduce (`test/wrappers.mjs`, "Senza componenti").
127
- - **Cambio pagina.** `pageKey` / `usePathname` / `astro:page-load` chiamano `pageView()`: le regole per pagina si ricalcolano e le richieste sono quelle giuste, senza duplicati.
128
- - **StrictMode e doppio montaggio.** Una sola istanza e un solo `init` per pagina.
129
- - **Eventi e targeting dall'inizio.** Si agganciano prima dell'`init`: `onEvent` riceve anche `ready` e `consent`, e il targeting vale per la prima richiesta.
126
+ - **Hydration.** UAL starts in an effect, after hydration. Loading the loader with a tag in the HTML before hydration makes React report *Hydration failed* (even with `suppressHydrationWarning`) and makes the slot be requested **twice**: the repository test reproduces it (`test/wrappers.mjs`, "Senza componenti").
127
+ - **Page change.** `pageKey` / `usePathname` / `astro:page-load` call `pageView()`: per-page rules are recomputed and the requests are the right ones, with no duplicates.
128
+ - **StrictMode and double mounting.** One instance and one `init` per page.
129
+ - **Events and targeting from the start.** They are attached before `init`: `onEvent` also receives `ready` and `consent`, and the targeting applies to the first request.
130
130
 
131
- ## Cosa resta uguale
131
+ ## What stays the same
132
132
 
133
- - **CSP rigida.** Le creatività girano in un iframe che eredita la CSP della pagina: senza `'unsafe-inline'` per script e stili il banner compare ma `UALExt` e il click tracciato non funzionano. Vedi il README.
134
- - **Un solo modo per pagina.** Non usare insieme il tag e i componenti sulla stessa pagina (il secondo `init` viene ignorato con un avviso).
135
- - **Versioni.** Con `src` (CDN) il loader può essere più vecchio o più nuovo del pacchetto: i componenti usano solo l'API comune e non richiedono `isInitialized`/`whenReady` (se mancano, chiamano `init`).
133
+ - **Strict CSP.** Creatives run in an iframe that inherits the page's CSP: without `'unsafe-inline'` for scripts and styles the banner shows up but `UALExt` and the tracked click do not work. See the README.
134
+ - **One mode per page.** Do not use the tag and the components together on the same page (the second `init` is ignored with a warning).
135
+ - **Versions.** With `src` (CDN) the loader may be older or newer than the package: the components use only the common API and do not require `isInitialized`/`whenReady` (if missing, they call `init`).
136
136
 
137
- ## Come è verificato
137
+ ## How it is verified
138
138
 
139
- `npm test` esegue, oltre ai test del loader:
139
+ `npm test` runs, besides the loader tests:
140
140
 
141
- - `test/package.mjs`: import in Node (ESM e CJS) senza `window`, errore chiaro di `getUal()` sul server, rendering sul server di React e Vue, mappa degli export, contenuto del pacchetto (`npm pack`), tipi (usi corretti compilano, quelli errati danno errore).
142
- - `test/wrappers.mjs`: in un browser vero, con rendering sul server e idratazione ritardata (il caso peggiore): React (UAL nel bundle, loader da CDN, versione Next), Vue, **Next.js 16** (App Router, build di produzione, Server Component, `<Link>`) e **Astro 7** (View Transitions). Per ognuno: nessun errore di idratazione, console pulita, una richiesta per slot, regole per pagina ricalcolate alla navigazione senza richieste doppie.
141
+ - `test/package.mjs`: import in Node (ESM and CJS) without `window`, clear `getUal()` error on the server, server rendering of React and Vue, exports map, package contents (`npm pack`), types (correct usages compile, wrong ones fail).
142
+ - `test/wrappers.mjs`: in a real browser, with server rendering and delayed hydration (the worst case): React (UAL in the bundle, loader from CDN, Next version), Vue, **Next.js 16** (App Router, production build, Server Component, `<Link>`) and **Astro 7** (View Transitions). For each: no hydration errors, clean console, one request per slot, per-page rules recomputed on navigation with no duplicate requests.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "universal-ad-loader",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Loader pubblicitario universale: un tag per sito, configurazione centralizzata, waterfall tra provider e consenso TCF. Componenti per React, Next.js, Vue e Astro.",
5
5
  "author": {
6
6
  "name": "ArdensLab",
@@ -36,7 +36,13 @@
36
36
  "main": "./dist/index.cjs",
37
37
  "module": "./dist/index.mjs",
38
38
  "types": "./dist/index.d.ts",
39
+ "browser": "./dist/ual.min.js",
40
+ "jsdelivr": "./dist/ual.min.js",
41
+ "unpkg": "./dist/ual.min.js",
39
42
  "sideEffects": false,
43
+ "engines": {
44
+ "node": ">=22"
45
+ },
40
46
  "exports": {
41
47
  ".": {
42
48
  "types": "./dist/index.d.ts",
@@ -71,6 +77,7 @@
71
77
  "astro",
72
78
  "schema",
73
79
  "docs",
80
+ "!docs/pubblicazione-npm.md",
74
81
  "CHANGELOG.md"
75
82
  ],
76
83
  "directories": {
@@ -1,114 +0,0 @@
1
- # Pubblicare `universal-ad-loader` su npm
2
-
3
- Si pubblica come `pm2-dash`: con la **CI di GitLab**, spingendo un branch dedicato (`deploy-npm`). Il pacchetto è già pronto (`universal-ad-loader`, MIT, autore ArdensLab, `publishConfig.access = public`, `prepack` che costruisce, `.gitlab-ci.yml`, `CHANGELOG.md`). Mancano solo i passaggi una tantum qui sotto, che richiedono le tue credenziali.
4
-
5
- La pubblicazione è **irreversibile**: una versione pubblicata si può solo deprecare (ritirarla è possibile solo entro 72 ore e se nessuno dipende da lei).
6
-
7
- ## Come funziona
8
-
9
- - **GitLab è l'unica CI.** Il repository di riferimento sta su GitLab (privato); GitHub (`ArdensLab/ual`) è solo un *push mirror* di `master`.
10
- - **Il branch `deploy-npm` è il comando di pubblicazione:** un push lì lancia la pipeline. Non `master`, non i tag.
11
- - **I tag** (`v0.1.0`…) sono marcatori di versione, come in `pm2-dash`: annotati, sul commit "Release X" in cui `package.json` ha quella versione. Non pubblicano nulla, ma la loro pipeline rilancia i test e il `release-check`.
12
-
13
- La pipeline (la stessa di `pm2-dash`, con in più i job che servono a un pacchetto con test in browser):
14
-
15
- | Stadio | Job | Cosa fa |
16
- |---|---|---|
17
- | test | `code_quality` | `oxlint` sui sorgenti, report nella merge request |
18
- | test | `test-node` (matrice Node **22 e 24**) | `npm run test:node`: import in Node (ESM e CJS), rendering sul server, mappa degli export, contenuto del tarball, tipi |
19
- | test | `test-browser` | `npm run test:browser`: loader e regressioni in Chromium (immagine Playwright) |
20
- | test | `test-frameworks` | `npm run test:frameworks`: React, Vue, **Next.js 16** (build di produzione) e **Astro 7**; l'unico che installa `test/heavy` |
21
- | test | `release-check` (solo tag e `deploy-*`) | il primo titolo del CHANGELOG è la versione di `package.json`; un tag è esattamente `v<versione>`; su `deploy-*` quella versione **non è già su npm** |
22
- | deploy | `npm-publish` | componente condiviso `matteo/ci-templates/npm-publish@1.5.0`: `npm ci` e `npm publish --access public` in `node:22` |
23
- | deploy | `gitlab-npm-publish` | stesso pacchetto sul registro npm di GitLab (`CI_JOB_TOKEN`, nessun segreto); parte **solo dopo** `npm-publish`, così un rifiuto di npm non lascia copie orfane |
24
-
25
- Tutti i job `test` pubblicano un report JUnit (scheda Tests della pipeline). Gli stadi sono in sequenza: **se un job di `test` fallisce, la pubblicazione non parte.**
26
-
27
- Perché è fatta così:
28
- - **Pesa poco.** I job leggeri installano solo la radice (~120 MB); Next.js e Astro (~620 MB) stanno in `test/heavy`, un progetto a parte con il proprio lockfile, che installa solo `test-frameworks`. I job girano in parallelo.
29
- - **La build sta in `prepack`:** il componente gira senza browser, quindi i test non possono stare in `prepublishOnly` (romperebbero il job). I test li esegue lo stadio `test`.
30
- - `release-check` fa fallire presto ciò che `npm publish` scoprirebbe tardi (versione già pubblicata, CHANGELOG dimenticato).
31
-
32
- ## Una tantum
33
-
34
- ### 1. Il nome: `universal-ad-loader`
35
- Storia dei nomi (2026-11-04), perché il nome si decide **solo pubblicando**:
36
-
37
- - `ual`: **non disponibile**, su npm è di un altro utente (`hedin_hiervard`, dal 2018, versioni 0.1.0, 0.1.1 e 1.0.0).
38
- - `@ardenslab/ual`: è stato pubblicato e poi ritirato (`Unpublished`): npm non permette più di riusare quella coppia nome e versione (`0.1.0`) e blocca il nome per 24 ore.
39
- - `ual-loader`: **rifiutato da npm** con `E403 Package name too similar to existing packages url-loader, raw-loader, null-loader, yaml-loader`. `npm view` lo dava libero: il filtro anti-typosquatting si applica ai nomi senza scope e si vede solo al momento della pubblicazione.
40
- - **`universal-ad-loader`**: libero (`npm view` dà E404). Se anche questo fosse rifiutato dal filtro, l'alternativa che npm suggerisce di solito è lo scope: `@ardenslab/universal-ad-loader` (lo scope `@ardenslab` è l'utente npm `ardenslab` e non è soggetto al filtro; basta aggiornare nome, import e documenti con la stessa sostituzione).
41
-
42
- Nessuna organizzazione da creare: si pubblica dall'utente npm **`ardenslab`**, lo stesso di `pm2-dash`.
43
-
44
- ### 2. Repository
45
- Segui la convenzione di `pm2-dash`, dentro `~/workspace/ArdensLab/` (là è configurata l'identità SSH di ArdensLab):
46
-
47
- 1. **Fatto (2026-11-04):** il progetto GitLab **`ardenslab/ual`** esiste (privato, id 95, creato con `glab api`) e il remoto `origin` è già collegato in questo repository (`ssh://git@gitlab.cloudnetwork.one:2222/ardenslab/ual.git`). `pm2-dash` risulta `internal` su GitLab: per cambiare visibilità, Settings ▸ General ▸ Visibility.
48
- 2. Fai il primo commit (il repository è già inizializzato, senza commit) e il push di `master`: `git push -u origin master`. **Poi imposta `master` come ramo predefinito**: GitLab ha creato il progetto con `main` e non permette di cambiarlo finché `master` non esiste (`glab api projects/95 -X PUT -f default_branch=master`, o Settings ▸ Repository ▸ Default branch).
49
- 3. Crea su GitHub il repository vuoto **`ArdensLab/ual`** (pubblico) e configura in GitLab il *push mirror* (Settings ▸ Repository ▸ Mirroring), solo `master`. Il campo `repository` di `package.json` punta già a `github.com/ArdensLab/ual`: se scegli un altro nome, cambialo prima di pubblicare, perché dopo si corregge solo con una nuova versione.
50
- 4. **Proteggi i branch di deploy** con la regola jolly **`deploy-*`** (Settings ▸ Repository ▸ Protected branches; push e merge solo Maintainer, niente force push), come in `pm2-dash`: altrimenti le variabili *Protected* arrivano vuote. **Fatto** su `ardenslab/ual` il 2026-11-04. Il branch `deploy-npm` non esiste finché non lo crea il primo push.
51
-
52
- ### 3. Il token
53
- Su npmjs.com ▸ Access Tokens ▸ *Granular Access Token*:
54
-
55
- - **Permessi:** lettura e scrittura. Per un nome **che non esiste ancora** npm non permette di limitare il token a quel pacchetto: per la **prima** pubblicazione serve un token con scrittura su *All packages*. **Subito dopo**, sostituiscilo con un token limitato al solo `universal-ad-loader` (come quello di `pm2-dash`) e aggiorna `NPM_TOKEN`: un token che può scrivere su tutti i pacchetti è più pericoloso se trapela.
56
- - **"Bypass 2FA" attivo:** la CI non può rispondere a una richiesta del codice. Se la casella non è davvero attiva il job fallisce con `EOTP` (è successo con `pm2-dash`): si rigenera il token con la casella spuntata, senza toccare il codice.
57
- - Annota la scadenza del token e rinnovalo.
58
-
59
- In GitLab (Settings ▸ CI/CD ▸ Variables) aggiungi **`NPM_TOKEN`** con **Masked** e **Protected**.
60
-
61
- ## Ogni rilascio
62
-
63
- ```bash
64
- npm version 0.1.1 --no-git-tag-version # la prima volta la versione è già 0.1.0: salta questo passo
65
- # aggiorna CHANGELOG.md (un blocco "# 0.1.1" in testa: lo richiede release-check)
66
- git commit -am "Release 0.1.1: <cosa cambia>"
67
- git push origin master # il mirror GitHub si aggiorna
68
- git push origin HEAD:deploy-npm # questo lancia la pubblicazione
69
- ```
70
-
71
- Quando la pipeline è verde e il pacchetto è su npm, **il tag** (annotato, sul commit di rilascio, come in `pm2-dash`) e la release GitLab:
72
-
73
- ```bash
74
- git tag -a v0.1.1 -m "Release 0.1.1"
75
- git push origin v0.1.1
76
- glab release create v0.1.1 --notes-file <(sed -n '/^# 0.1.1/,/^# /p' CHANGELOG.md | sed '$d') # la pagina Release, con le note del CHANGELOG
77
- ```
78
-
79
- Il push del tag lancia la pipeline di tag (test e `release-check`, nessuna pubblicazione): se il tag non è `v<versione>` fallisce.
80
-
81
- Poi controlla:
82
-
83
- ```bash
84
- npm view universal-ad-loader version # la versione appena pubblicata
85
- ```
86
-
87
- e prova `npm i universal-ad-loader` in un progetto vuoto.
88
-
89
- Sotto la `1.0.0` l'API può ancora cambiare tra una versione minor e l'altra: è il significato di `0.x`. Dopo ogni rilascio ricostruisci `dist/ual.min.js` e caricalo anche sulla CDN (meglio in un percorso con la versione, vedi `docs/cdn.md`). Una versione sbagliata si segnala con `npm deprecate universal-ad-loader@0.1.0 "usa 0.1.1"`.
90
-
91
- ## Subito dopo la prima pubblicazione
92
-
93
- - Nel configuratore (`ual-configurator/src/lib/output.ts`) imposta `PACKAGE_PUBLISHED = true`: l'avviso «non ancora pubblicato» sparisce dalla scheda Snippet. Aggiorna le frasi «non ancora pubblicato» in `docs/libreria.md`, nel README del loader e nella guida (`docs.astro`).
94
-
95
- ## Pubblicare a mano (emergenza)
96
-
97
- Possibile, ma senza la rete di sicurezza della pipeline:
98
-
99
- ```bash
100
- npm login # come utente ardenslab, con 2FA
101
- npm test # la build la fa prepack, i test NON partono da soli
102
- npm publish # chiede il codice della 2FA
103
- ```
104
-
105
- ## Provenance
106
-
107
- `npm publish --provenance` allega un'attestazione firmata di quale commit e quale pipeline hanno prodotto il pacchetto, ma funziona solo da una CI con **repository pubblico**. `pm2-dash` non la usa (GitLab privato, GitHub è solo uno specchio): lo stesso vale qui.
108
-
109
- ## Cosa significa rendere pubblico il pacchetto
110
-
111
- - Il codice (compresi i controlli di sicurezza del render) è leggibile da chiunque: i difetti vanno corretti prima, non dopo.
112
- - La licenza MIT permette a chiunque di usarlo e modificarlo, anche commercialmente, e non si può ritirare per le versioni già pubblicate.
113
- - Gli adapter `adsense`, `revive-async` e `gpt` sono scritti sulle API pubbliche ma non provati su account reali (`gpt` solo con uno stub): il README lo dichiara, e conviene tenerlo visibile.
114
- - Possono arrivare segnalazioni e richieste: decidi se e come rispondere.