@emplugins/emprivacy 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,19 +6,21 @@
6
6
 
7
7
  ## Requirements
8
8
 
9
- - **EmDash** `>=0.14.0` (**tested with `0.14.0` and `0.29.0`**; see [EMDASH_COMPAT.md](./EMDASH_COMPAT.md)). Sites on EmDash 0.9–0.13: use **emprivacy 0.2.x**.
10
- - Plugins registered in **`astro.config`** in **trusted** mode (the `plugins: []` array).
11
- **Sandboxed** marketplace plugins **cannot** use `page:fragments`; EmPrivacy needs the `hooks.page-fragments:register` capability so head/body contributions run on public pages. See [Plugin System Overview](https://docs.emdashcms.com/plugins/overview/).
9
+ - **EmDash** `^0.38.0` (**tested with `0.38.0`**; re-test on your deployed minor when upgrading).
10
+ - **Node.js** `>= 22.16` (matches EmDash’s engine requirement).
11
+ - Register as a **native** plugin in **`astro.config`** via `plugins: []` (not `sandboxed: []`). EmPrivacy uses `page:fragments` for the public banner and scripts; that hook only runs for trusted in-process plugins. See [Page fragments](https://docs.emdashcms.com/plugins/creating-native-plugins/page-fragments/) and [Plugin overview](https://docs.emdashcms.com/plugins/overview/).
12
12
 
13
13
  ## Install
14
14
 
15
15
  ```bash
16
+ pnpm add @emplugins/emprivacy
17
+ # or
16
18
  npm install @emplugins/emprivacy
17
19
  ```
18
20
 
19
- Published under the [emplugins](https://www.npmjs.com/org/emplugins) npm org. Source: [github.com/EmPlugins/EmPrivacy](https://github.com/EmPlugins/EmPrivacy).
21
+ Published under the [emplugins](https://www.npmjs.com/org/emplugins) npm org. Source: [github.com/EmPlugins/EmPrivacy](https://github.com/EmPlugins/EmPrivacy). See [EMDASH_COMPAT.md](./EMDASH_COMPAT.md) for EmDash version mapping.
20
22
 
21
- Use a **semver range** if you want controlled upgrades, for example `@emplugins/emprivacy@^1.0.0`. Versioning policy and maintainer release steps: [docs/RELEASES.md](docs/RELEASES.md). Org publish / `NPM_TOKEN` setup: [docs/NPM_ORG_PUBLISH.md](docs/NPM_ORG_PUBLISH.md).
23
+ Use a **semver range** if you want controlled upgrades, for example `@emplugins/emprivacy@^1.0.0`. Versioning: [docs/RELEASES.md](docs/RELEASES.md). Org publish: [docs/NPM_ORG_PUBLISH.md](docs/NPM_ORG_PUBLISH.md).
22
24
 
23
25
  The legacy unscoped package `emprivacy` is deprecated; migrate imports to `@emplugins/emprivacy`.
24
26
 
@@ -28,7 +30,7 @@ The legacy unscoped package `emprivacy` is deprecated; migrate imports to `@empl
28
30
 
29
31
  ```ts
30
32
  import { defineConfig } from "astro/config";
31
- import { emdash } from "emdash/astro";
33
+ import emdash from "emdash/astro";
32
34
  import { emprivacyPlugin } from "@emplugins/emprivacy";
33
35
 
34
36
  export default defineConfig({
@@ -40,7 +42,9 @@ The legacy unscoped package `emprivacy` is deprecated; migrate imports to `@empl
40
42
  });
41
43
  ```
42
44
 
43
- 2. **Use EmDash page integration** in your layout so fragments render: include `<EmDashHead />`, `<EmDashBodyStart />`, `<EmDashBodyEnd />` (or your theme’s equivalents). See [EmDash docs](https://docs.emdashcms.com/).
45
+ Native descriptors belong in `plugins`, not `sandboxed`. EmDash loads the named `createPlugin()` export from the package at runtime.
46
+
47
+ 2. **Use EmDash page integration** in your layout so fragments render: include `<EmDashHead />`, `<EmDashBodyStart />`, `<EmDashBodyEnd />` (or your theme’s equivalents), typically with a shared `createPublicPageContext({ Astro, … })`. See [EmDash page fragments](https://docs.emdashcms.com/plugins/creating-native-plugins/page-fragments/).
44
48
 
45
49
  3. **Configure EmPrivacy in the admin** (shield → **EmPrivacy**):
46
50
  - **Privacy policy** — Point to your existing EmDash **Page** using its **public path** (what you see in the address bar when that Page is open, e.g. `/privacy`), **or** a full `https://…` URL if the policy is hosted elsewhere. Root-relative paths are resolved with EmDash `ctx.url()` so links stay correct across environments.
@@ -64,6 +68,14 @@ Visitors see a banner on first visit (or when you bump **Policy / consent versio
64
68
  | Optional server log | POST consent snapshots to `/_emdash/api/plugins/emprivacy/record` + optional storage rows (no IP in v1) |
65
69
  | Google Consent Mode v2 | Optional denied defaults in `<head>` + `gtag('consent','update',…)` — validate with [Google’s docs](https://support.google.com/tagmanager/answer/13695607) |
66
70
 
71
+ ## Capabilities
72
+
73
+ | Capability | Why |
74
+ |------------|-----|
75
+ | `hooks.page-fragments:register` | Public banner, styles, and consent bootstrap scripts |
76
+
77
+ Settings, KV, and declared plugin storage need no extra capability. Native plugins are not an isolation boundary: review and install this package like first-party site code.
78
+
67
79
  ## Legal disclaimer
68
80
 
69
81
  EmPrivacy helps you implement **technical** consent UX and script loading patterns used for regulations such as **GDPR** and **CCPA/CIPA**. **You** remain responsible for:
@@ -81,16 +93,16 @@ Put **`emprivacyPlugin()` early** in the `plugins` array so `page:metadata` / `p
81
93
  ## Development
82
94
 
83
95
  ```bash
84
- npm install
85
- npm run typecheck # TypeScript
86
- npm run build # ESM + types in dist/
87
- npm test # Unit tests (see Testing)
88
- npm run test:watch # Vitest in watch mode (optional)
96
+ pnpm install
97
+ pnpm run typecheck # TypeScript
98
+ pnpm run build # ESM + types in dist/
99
+ pnpm test # Unit tests (see Testing)
100
+ pnpm run test:watch # Vitest in watch mode (optional)
89
101
  ```
90
102
 
91
- Outputs ESM under `dist/` with typings, matching the [plugin layout](https://www.npmjs.com/package/@emdash-cms/plugin-audit-log) used by other EmDash packages.
103
+ Outputs ESM under `dist/` with typings. Layout follows EmDash’s [native plugin packaging](https://docs.emdashcms.com/plugins/creating-native-plugins/distributing/) (`emprivacyPlugin()` descriptor + named `createPlugin()`).
92
104
 
93
- Dependency, audit, and deprecation context (Kysely override, `npm audit`): [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md).
105
+ Dependency, audit, and deprecation context: [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md).
94
106
 
95
107
  ## Testing
96
108
 
@@ -132,13 +144,11 @@ Details: [docs/TESTING.md](docs/TESTING.md).
132
144
  - [ ] Admin save updates the public banner
133
145
  - [ ] Optional: server logging + recent records in admin
134
146
  - [ ] Optional: Google Consent Mode (Tag Assistant / [Google](https://support.google.com/tagmanager/answer/13695607))
135
- - [ ] **Trusted** `plugins: []` (see [Requirements](#requirements))
147
+ - [ ] Native `plugins: []` registration (see [Requirements](#requirements))
136
148
 
137
149
  ## Releases
138
150
 
139
- npm releases follow **[Semantic Versioning](https://semver.org/)** (`MAJOR.MINOR.PATCH`). Tags are `v`-prefixed (e.g. `v0.1.0`). See [docs/RELEASES.md](docs/RELEASES.md).
140
-
141
- **EmDash upgrades:** say `update to latest emdash release` in Cursor (skill: [`.cursor/skills/emdash-release`](.cursor/skills/emdash-release/SKILL.md)) to bump, test, and publish to npm + GitHub without a manual merge gate.
151
+ npm releases follow **[Semantic Versioning](https://semver.org/)** (`MAJOR.MINOR.PATCH`). Tags are `v`-prefixed (e.g. `v0.2.1`). See [docs/RELEASES.md](docs/RELEASES.md) for bump rules, `npm version` / `npm run release:*`, and publish checklist.
142
152
 
143
153
  ## License
144
154
 
package/dist/index.d.mts CHANGED
@@ -1,11 +1,87 @@
1
- import { a as EmprivacyConfig, c as isRootRelativeSitePath, d as resolvePolicyHref, i as DEFAULT_CONFIG, l as isValidPolicyHrefInput, n as COOKIE_NAME, o as KV_KEY, r as ConsentRecordPayload, s as assertValidCloudflareToken, t as AnalyticsProvider, u as normalizeConfig } from "./config-CqOtRoQR.mjs";
1
+ import * as emdash from "emdash";
2
2
  import { PluginDescriptor } from "emdash";
3
3
 
4
+ //#region src/runtime.d.ts
5
+ /**
6
+ * Native EmDash runtime — loaded via the named `createPlugin` export.
7
+ * Uses `page:fragments`, which requires trusted in-process (native) execution.
8
+ */
9
+ declare function createPlugin(): emdash.ResolvedPlugin<{
10
+ consentEvents: {
11
+ indexes: string[];
12
+ };
13
+ }>;
14
+ //#endregion
15
+ //#region src/config.d.ts
16
+ /**
17
+ * EmPrivacy KV document (`consent:config`) and shared helpers.
18
+ */
19
+ declare const KV_KEY: "consent:config";
20
+ declare const COOKIE_NAME: "emprivacy_cc";
21
+ /** How analytics scripts are chosen after the user consents to analytics. */
22
+ type AnalyticsProvider = "cloudflare" | "none" | "custom";
23
+ interface EmprivacyConfig {
24
+ bannerTitle: string;
25
+ bannerMessage: string;
26
+ /**
27
+ * Privacy policy location: full `https://…` URL **or** a root-relative path to an EmDash **Page**
28
+ * (e.g. `/privacy`) resolved with `ctx.url()` on the server.
29
+ */
30
+ privacyPolicyUrl: string;
31
+ /** Optional cookie policy: same rules as `privacyPolicyUrl` (https URL or path like `/cookies`) */
32
+ cookiePolicyUrl: string;
33
+ /** When true, analytics/marketing require explicit opt-in in the UI */
34
+ strictDefaults: boolean;
35
+ /** Bump to invalidate client consent cookies and re-show the banner */
36
+ policyVersion: string;
37
+ /**
38
+ * Analytics when `cloudflare` — **site token** from Cloudflare → Web Analytics (injected with `data-cf-beacon`).
39
+ * Public in the same way as a normal site embed. Empty means no Cloudflare script until a token is saved.
40
+ */
41
+ cloudflareWebAnalyticsToken: string;
42
+ /**
43
+ * Which analytics load path to use after consent. `cloudflare` = beacon + `cloudflareWebAnalyticsToken`;
44
+ * `custom` = `analyticsScriptUrls` only; `none` = no third-party analytics scripts.
45
+ */
46
+ analyticsProvider: AnalyticsProvider;
47
+ /** When `analyticsProvider` is `custom`, these https script URLs load after analytics consent. */
48
+ analyticsScriptUrls: string[];
49
+ /** Third-party script URLs loaded only after marketing consent (https only) */
50
+ marketingScriptUrls: string[];
51
+ /** Emit Google Consent Mode v2 defaults (denied) in head; updates after choice */
52
+ googleConsentMode: boolean;
53
+ /** POST consent snapshots to the plugin record route and optional storage */
54
+ logConsentToServer: boolean;
55
+ }
56
+ declare const DEFAULT_CONFIG: EmprivacyConfig;
57
+ /** Reject characters that would break JSON or attributes; allow typical Cloudflare site token strings. */
58
+ declare function assertValidCloudflareToken(t: string): void;
59
+ /**
60
+ * Root-relative public path (EmDash page route), e.g. `/privacy`.
61
+ * Rejects protocol-relative URLs (`//…`) and whitespace.
62
+ */
63
+ declare function isRootRelativeSitePath(s: string): boolean;
64
+ /** For hooks: turn stored path or absolute URL into a public absolute URL. */
65
+ declare function resolvePolicyHref(stored: string, ctx: {
66
+ url: (path: string) => string;
67
+ }): string;
68
+ declare function isValidPolicyHrefInput(s: string): boolean;
69
+ declare function normalizeConfig(raw: unknown): EmprivacyConfig;
70
+ interface ConsentRecordPayload {
71
+ createdAt: string;
72
+ policyVersion: string;
73
+ analytics: boolean;
74
+ marketing: boolean;
75
+ }
76
+ //#endregion
4
77
  //#region src/index.d.ts
5
78
  /**
6
- * EmDash plugin descriptor — add to `plugins: []` in `emdash({ ... })` inside `astro.config`.
7
- * Requires **trusted** registration so `page:metadata` / `page:fragments` run (sandboxed plugins cannot inject fragments).
79
+ * EmDash native plugin descriptor — add to `plugins: []` in `emdash({ ... })` inside `astro.config`.
80
+ *
81
+ * EmPrivacy uses `page:fragments` (banner + consent scripts), which only runs for **native**
82
+ * plugins registered in `plugins: []`. Do not place this descriptor in `sandboxed: []`.
83
+ * See [Page fragments](https://docs.emdashcms.com/plugins/creating-native-plugins/page-fragments/).
8
84
  */
9
85
  declare function emprivacyPlugin(): PluginDescriptor;
10
86
  //#endregion
11
- export { type AnalyticsProvider, COOKIE_NAME, type ConsentRecordPayload, DEFAULT_CONFIG, type EmprivacyConfig, KV_KEY, assertValidCloudflareToken, emprivacyPlugin, isRootRelativeSitePath, isValidPolicyHrefInput, normalizeConfig, resolvePolicyHref };
87
+ export { type AnalyticsProvider, COOKIE_NAME, type ConsentRecordPayload, DEFAULT_CONFIG, type EmprivacyConfig, KV_KEY, assertValidCloudflareToken, createPlugin, createPlugin as default, emprivacyPlugin, isRootRelativeSitePath, isValidPolicyHrefInput, normalizeConfig, resolvePolicyHref };