@bloomscorp/blooms-ai-embed 0.1.1 → 0.2.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/CHANGELOG.md +98 -0
- package/README.md +76 -3
- package/dist/blooms-embed.js +1 -10
- package/dist/chunk-3U3MLDTP.js +1 -0
- package/dist/chunk-4PL37FNN.js +74 -0
- package/dist/chunk-53INJES5.js +1 -0
- package/dist/chunk-5NLZKRFI.js +3 -0
- package/dist/chunk-7ENRHCKA.js +3 -0
- package/dist/chunk-7NQRVCWL.js +1 -0
- package/dist/chunk-ACC77NVF.js +3 -0
- package/dist/chunk-EA7SZINY.js +1 -0
- package/dist/chunk-GWYYXSOG.js +3 -0
- package/dist/chunk-HLIQJSA7.js +24 -0
- package/dist/chunk-IRBW4XXQ.js +1 -0
- package/dist/chunk-OBI6OSSF.js +1 -0
- package/dist/chunk-OSBW6YXS.js +1 -0
- package/dist/chunk-OSUK4H76.js +3 -0
- package/dist/chunk-QVZ2D36I.js +1 -0
- package/dist/chunk-RL3EC5EG.js +3 -0
- package/dist/chunk-SPLW6L45.js +2 -0
- package/dist/chunk-T4IZD3WN.js +1 -0
- package/dist/chunk-UQVX3SID.js +3 -0
- package/dist/chunk-VQEBAAHK.js +1 -0
- package/dist/chunk-WFG2A6RA.js +3 -0
- package/dist/chunk-WQW7QCHM.js +7 -0
- package/dist/chunk-X2Q5WSIJ.js +2 -0
- package/dist/chunk-X5SAQDWB.js +3 -0
- package/dist/chunk-XZWMQ7QK.js +3 -0
- package/dist/chunk-YDIWMCSH.js +3 -0
- package/dist/chunk-ZZTWS6NP.js +3 -0
- package/dist/index.d.ts +221 -3
- package/dist/index.js +16 -6
- package/package.json +5 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,104 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@bloomscorp/blooms-ai-embed`.
|
|
4
4
|
|
|
5
|
+
## 0.2.0
|
|
6
|
+
|
|
7
|
+
Twelve new components, and the bundle is now code-split so adopting one does not
|
|
8
|
+
cost you all of them.
|
|
9
|
+
|
|
10
|
+
Upgrading is a drop-in **unless you branch on `customElements.get()`** or stage
|
|
11
|
+
`dist/` by hand — see *Action if you are upgrading* below.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **Twelve new elements.** `<blooms-login>` is no longer the only thing you can
|
|
16
|
+
embed:
|
|
17
|
+
|
|
18
|
+
| | | |
|
|
19
|
+
|---|---|---|
|
|
20
|
+
| `<blooms-crawl-insights>` | `<blooms-sitemap-crawl>` | `<blooms-sitemap-crawl-detail>` |
|
|
21
|
+
| `<blooms-keywords>` | `<blooms-keyword-detail>` | `<blooms-reports>` |
|
|
22
|
+
| `<blooms-gmc-analytics>` | `<blooms-social-media-calendar>` | `<blooms-smc-day-detail>` |
|
|
23
|
+
| `<blooms-influencer-dashboard>` | `<blooms-influencer-detail>` | `<blooms-blog-strategy>` |
|
|
24
|
+
|
|
25
|
+
Each takes its state through attributes or properties rather than a URL, since
|
|
26
|
+
a custom element cannot read the host page's address bar: `project-id` on most,
|
|
27
|
+
plus `crawl-id`, `keyword-id`, `influencer-id`, `strategy-id`, `event-id`,
|
|
28
|
+
`date-iso` where the component addresses one record. Components that used to
|
|
29
|
+
navigate now emit a `bloomsnavigate` event describing where they would have
|
|
30
|
+
gone — your app decides what that means.
|
|
31
|
+
|
|
32
|
+
Declared in `HTMLElementTagNameMap`, so TypeScript knows all thirteen tags.
|
|
33
|
+
|
|
34
|
+
- **`preload(...features)`.** Fetches a component's code before it is needed:
|
|
35
|
+
|
|
36
|
+
```js
|
|
37
|
+
await BloomsEmbed.preload('crawl-insights', 'keywords');
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Optional and never throws — a failed preload just means the chunk is fetched
|
|
41
|
+
later, when the component is actually mounted.
|
|
42
|
+
|
|
43
|
+
### Changed
|
|
44
|
+
|
|
45
|
+
- **The bundle is code-split: one lazily-fetched chunk per component.** Shipping
|
|
46
|
+
thirteen components eagerly had grown the download to 162 kB gzipped, with the
|
|
47
|
+
three largest still unconverted — so every host paid for every component to use
|
|
48
|
+
one. Now:
|
|
49
|
+
|
|
50
|
+
| | Transfer (gzipped) |
|
|
51
|
+
|---|---|
|
|
52
|
+
| Loader + shared core | **~65 kB** |
|
|
53
|
+
| …plus one component | ~69 kB |
|
|
54
|
+
| …plus all thirteen | ~180 kB |
|
|
55
|
+
|
|
56
|
+
`dist/blooms-embed.js` is a ~3 kB loader; the components live in sibling
|
|
57
|
+
`dist/chunk-*.js` files that it imports by relative path on first use.
|
|
58
|
+
|
|
59
|
+
- **Elements are defined on demand, not at import.** A tag is registered the
|
|
60
|
+
first time an instance of it appears, and the browser upgrades the element that
|
|
61
|
+
was already there. Tags in your HTML behave exactly as before and there is
|
|
62
|
+
nothing to await. One observable difference:
|
|
63
|
+
|
|
64
|
+
```js
|
|
65
|
+
import { BloomsEmbed } from '@bloomscorp/blooms-ai-embed';
|
|
66
|
+
customElements.get('blooms-crawl-insights'); // undefined until one is used
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Setting a **property** before a component's chunk arrives is safe — the value
|
|
70
|
+
is applied once the component is defined. Attributes were never affected.
|
|
71
|
+
|
|
72
|
+
- **Write actions are enabled** for Social Media Calendar, Influencers and Blog
|
|
73
|
+
Strategy — create, edit, reschedule, delete, and the AI generation steps. They
|
|
74
|
+
were read-only in `0.1.x`, with controls that rendered and then returned 403.
|
|
75
|
+
|
|
76
|
+
### Action if you are upgrading
|
|
77
|
+
|
|
78
|
+
1. **If you bundle the package** (the recommended setup, and what the Electron
|
|
79
|
+
guide describes) — nothing to do. Webpack, Vite, esbuild and Rollup all follow
|
|
80
|
+
the dynamic imports and emit their own chunks.
|
|
81
|
+
|
|
82
|
+
2. **If you stage `dist/` by hand**, copy **all** of it. `chunk-*.js` must sit in
|
|
83
|
+
the same directory as `blooms-embed.js`. Copying only the entry leaves you with
|
|
84
|
+
a package that installs cleanly and renders every component as a blank
|
|
85
|
+
element, with one console error per component as the only clue.
|
|
86
|
+
|
|
87
|
+
3. **Remove any `customElements.get()` guard** around showing a component. It was
|
|
88
|
+
reliable in `0.1.x` because every tag was defined at import; it is not now.
|
|
89
|
+
Place the tag, or call `mount()`, and let the loader do its work.
|
|
90
|
+
|
|
91
|
+
### Known gaps, stated so they are not surprises
|
|
92
|
+
|
|
93
|
+
- `<blooms-keyword-detail>`'s Search Console section is **empty when embedded**.
|
|
94
|
+
The underlying route takes its project id as a query parameter and carries no
|
|
95
|
+
authorization of its own, and our allowlist pins project ids in the path — so
|
|
96
|
+
exposing it would have handed every embedded session cross-project Search
|
|
97
|
+
Console data. The route is being fixed rather than the allowlist widened.
|
|
98
|
+
- Report generation (Crawl Insights) and bulk delete (Reports) are hidden when
|
|
99
|
+
embedded: their output is delivered to the blooms.ai portal, which a host app
|
|
100
|
+
cannot reach. Starting a job whose result you cannot collect is worse than not
|
|
101
|
+
offering it.
|
|
102
|
+
|
|
5
103
|
## 0.1.1
|
|
6
104
|
|
|
7
105
|
Everything here came from the first production Electron integration reporting
|
package/README.md
CHANGED
|
@@ -59,11 +59,49 @@ That is the whole integration. Importing the package defines the elements and in
|
|
|
59
59
|
`<blooms-login>` renders the sign-in form, remembers the session across reloads, and revalidates
|
|
60
60
|
it on the next load.
|
|
61
61
|
|
|
62
|
+
### Elements in this bundle
|
|
63
|
+
|
|
64
|
+
| Tag | What it renders | Token ceiling it needs |
|
|
65
|
+
|---|---|---|
|
|
66
|
+
| `<blooms-login>` | Sign-in form, session persistence, precise error states | — |
|
|
67
|
+
| `<blooms-crawl-insights>` | Crawl results: pages crawled, broken links, page issues, missing meta, duplicate titles, health score. Starts crawls and re-scans single URLs. | `crawl-insights` (or `crawl`) |
|
|
68
|
+
| `<blooms-sitemap-crawl>` | Crawl from a sitemap: start a run, watch progress, browse history. | `sitemap` (or `crawl`) |
|
|
69
|
+
| `<blooms-sitemap-crawl-detail>` | One sitemap run in detail. Takes `crawl-id`. | `sitemap` (or `crawl`) |
|
|
70
|
+
| `<blooms-keywords>` | Tracked keywords: rank, volume, difficulty, trend. Adds keywords, triggers a rank sync. | `manager` |
|
|
71
|
+
| `<blooms-keyword-detail>` | One keyword in detail. Takes `keyword-id`. Its Search Console section is empty when embedded — see below. | `manager` |
|
|
72
|
+
| `<blooms-reports>` | Report list and downloads. Generation and bulk delete are hidden when embedded. | `manager` |
|
|
73
|
+
| `<blooms-gmc-analytics>` | Google Merchant Centre overview: feed health, disapprovals, account issues. | `manager` |
|
|
74
|
+
| `<blooms-social-media-calendar>` | Content calendar: month and list views, statuses, attachments, assignees. Create, edit, reschedule, delete. Takes `event-id` to deep-link a drawer. | `social-media-calendar` |
|
|
75
|
+
| `<blooms-smc-day-detail>` | One day of the calendar. Takes `date-iso` (`YYYY-MM-DD`), required. | `social-media-calendar` |
|
|
76
|
+
| `<blooms-influencer-dashboard>` | Tracked influencers with tiers, platforms, latest metrics. Create and edit. | `influencer-management` |
|
|
77
|
+
| `<blooms-influencer-detail>` | One influencer: profile, platforms, snapshots. Takes `influencer-id`. | `influencer-management` |
|
|
78
|
+
| `<blooms-blog-strategy>` | The blog authoring workflow: topic → SEO research → outline → draft → visuals → metadata → review → publish → promotion → performance. Takes `strategy-id` and `step`. | `blog-publishing` |
|
|
79
|
+
|
|
80
|
+
A `manager` or `owner` ceiling covers all of them, so one token needs no edit as
|
|
81
|
+
you adopt more. The keys above matter only for a deliberately narrow ceiling —
|
|
82
|
+
and Keywords, Reports and GMC are gated on `manager` itself, so a narrow ceiling
|
|
83
|
+
cannot include them without including everything. A ceiling is never a grant: the
|
|
84
|
+
signed-in user's own per-project permissions are evaluated on every request.
|
|
85
|
+
|
|
86
|
+
Components that would navigate emit `bloomsnavigate` instead of routing — the
|
|
87
|
+
detail is in the Electron guide, and the payload is typed.
|
|
88
|
+
|
|
89
|
+
**Two deliberate gaps.** `<blooms-keyword-detail>`'s Search Console section is
|
|
90
|
+
empty when embedded: that route takes its project id as a query parameter and has
|
|
91
|
+
no authorization of its own, so exposing it would leak cross-project data — being
|
|
92
|
+
fixed server-side. Report generation and bulk delete are hidden because their
|
|
93
|
+
output is delivered to the blooms.ai portal, which your app cannot reach.
|
|
94
|
+
|
|
95
|
+
Feature elements render a sign-in prompt until a session exists, so you can place them
|
|
96
|
+
unconditionally. Each takes an optional `project-id`; omit it and the element follows the
|
|
97
|
+
session's active project, so `BloomsEmbed.setProject()` moves it.
|
|
98
|
+
|
|
62
99
|
Three things worth knowing:
|
|
63
100
|
|
|
64
|
-
- **`configure()` once, early.**
|
|
65
|
-
|
|
66
|
-
showing a skeleton meanwhile — so a slow `configure()`
|
|
101
|
+
- **`configure()` once, early.** An element placed in your HTML is upgraded when its chunk
|
|
102
|
+
arrives, which may be before or after your `configure()` call. Either order is fine: it waits
|
|
103
|
+
for configuration rather than failing, showing a skeleton meanwhile — so a slow `configure()`
|
|
104
|
+
is a slow first paint, not an error.
|
|
67
105
|
- **`apiBase` is optional** when you load the bundle from blooms.ai, because it defaults to the
|
|
68
106
|
bundle's own origin. When you install from npm the bundle's origin is *your* app, so **pass
|
|
69
107
|
`apiBase` explicitly**.
|
|
@@ -79,6 +117,7 @@ Three things worth knowing:
|
|
|
79
117
|
| `version` | `string` | Bundle version. |
|
|
80
118
|
| `configure` | `(config: BloomsEmbedConfig) => void` | Call first. Throws on a missing token or a token that is not `blm_embed_…`. |
|
|
81
119
|
| `mode` | `() => 'element' \| 'iframe' \| null` | The resolved rendering mode; `null` before `configure()`. |
|
|
120
|
+
| `preload` | `(...features: string[]) => Promise<void>` | Warms a component's lazy chunk before it is used. Optional, never throws. |
|
|
82
121
|
| `manifest` | `() => Promise<EmbedManifest>` | Pre-login bootstrap: project name, enabled features, theme, branding flag, session TTL. |
|
|
83
122
|
| `login` | `({ email, password }) => Promise<EmbedSessionState>` | Programmatic alternative to `<blooms-login>`, for hosts with their own form. |
|
|
84
123
|
| `session` | `() => EmbedSessionState \| null` | The current session, restored from storage by `configure()`. Synchronous. |
|
|
@@ -409,6 +448,40 @@ In Electron, that also means: import it in the **renderer**, never in the main p
|
|
|
409
448
|
|
|
410
449
|
---
|
|
411
450
|
|
|
451
|
+
## Lazy loading
|
|
452
|
+
|
|
453
|
+
The bundle is code-split: a small loader plus one chunk per component, fetched the first time that
|
|
454
|
+
component is used. A page embedding one component downloads one component (~69 kB gzipped, against
|
|
455
|
+
~180 kB for the full set).
|
|
456
|
+
|
|
457
|
+
Nothing in your markup changes. A tag in your HTML is defined when its chunk arrives and the
|
|
458
|
+
browser upgrades the element that was already there. You never await anything.
|
|
459
|
+
|
|
460
|
+
Three things worth knowing:
|
|
461
|
+
|
|
462
|
+
- **Do not gate your UI on `customElements.get(tag)`.** It returns `undefined` until that
|
|
463
|
+
component has been used once. Before code splitting it was defined immediately, so a check like
|
|
464
|
+
this used to pass:
|
|
465
|
+
|
|
466
|
+
```js
|
|
467
|
+
import { BloomsEmbed } from '@bloomscorp/blooms-ai-embed';
|
|
468
|
+
if (customElements.get('blooms-keywords')) { /* no longer true up front */ }
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
- **Setting properties early is safe.** `el.projectId = '...'` on an element whose chunk has not
|
|
472
|
+
arrived is preserved and applied once the component is defined. Attributes were never affected.
|
|
473
|
+
|
|
474
|
+
- **Warm a chunk if you know what is next:**
|
|
475
|
+
|
|
476
|
+
```js
|
|
477
|
+
await BloomsEmbed.preload('crawl-insights', 'keywords');
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
If you stage `dist/` by hand instead of importing the package, copy **all** of it — `chunk-*.js`
|
|
481
|
+
must stay beside `blooms-embed.js`, and `media/*.woff2` beside the stylesheet.
|
|
482
|
+
|
|
483
|
+
---
|
|
484
|
+
|
|
412
485
|
## Security notes worth reading once
|
|
413
486
|
|
|
414
487
|
- The embed token is publishable, but it is not a secret to be careless with: it is what ties
|